mirror of
https://github.com/sasjs/core.git
synced 2025-12-11 06:24:35 +00:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c67a07e42 | ||
|
|
187504600a | ||
|
|
658d67feaa | ||
|
|
5207a77591 | ||
|
|
4456adf1dc | ||
|
|
03962c2a50 | ||
|
|
6d2fc7e265 | ||
|
|
39b2e7c5f9 | ||
|
|
f99adf5c3e | ||
|
|
69f8e91a2d | ||
|
|
5b5d01993f | ||
|
|
00fa464a7c | ||
|
|
a5baf46233 | ||
|
|
d63d2a4ec1 | ||
|
|
900f694065 | ||
|
|
838324c15e | ||
|
|
e3205ec06c | ||
|
|
154a33434e | ||
|
|
bfa1bbaeb1 | ||
|
|
1f0128aec4 | ||
|
|
69f03f4e14 | ||
|
|
a932f321d8 | ||
|
|
21200c11c1 | ||
|
|
825c97c49c | ||
|
|
f301899269 | ||
|
|
fc81f62d2f | ||
|
|
93aea5ed02 | ||
|
|
55d4c7238a | ||
|
|
cd75bf263a | ||
|
|
929a1a9974 | ||
|
|
7cafb4fb36 | ||
|
|
a8d222a0f8 | ||
|
|
ac0ddf38b0 | ||
|
|
ecd389c935 | ||
|
|
06a5ea06f8 | ||
|
|
955471ed3c | ||
|
|
c8d3b43b12 | ||
|
|
3e313b06a9 | ||
|
|
d7371a4505 | ||
|
|
32a6d15c2e | ||
|
|
b109e7cead | ||
| d291d3e287 | |||
|
|
5a2968e798 | ||
|
|
120ad9a7da | ||
|
|
67a81b2690 | ||
|
|
506cf1812f | ||
|
|
8cc0eb0dd7 | ||
|
|
4c1f69da3a | ||
|
|
f160ebe705 | ||
|
|
3f49925d01 | ||
|
|
53ed5dc916 | ||
|
|
808b24e31b | ||
|
|
c51c9c2ca9 | ||
|
|
4d6edf5566 | ||
|
|
41a24677f5 | ||
|
|
e7d8d8ffb3 | ||
|
|
60d23dd618 | ||
|
|
d2764c3cd1 | ||
|
|
f9f4355143 | ||
|
|
18bc6c889d | ||
|
|
42a16ef496 | ||
|
|
8178b801fb | ||
|
|
ce331a23c8 | ||
|
|
1cc9213467 | ||
|
|
aabbf4d0f9 | ||
|
|
2bea8be70d | ||
|
|
9b2368443e | ||
|
|
7915ba2c41 | ||
|
|
cc61e48868 | ||
|
|
62db83dcf6 | ||
|
|
7ea9e0f8e9 | ||
|
|
1c852515f5 | ||
|
|
b7e677bd8e | ||
|
|
f47f0d2cee | ||
|
|
3d0f426a98 | ||
|
|
2cb51f6164 | ||
|
|
b73bf998da | ||
|
|
c9ad38ee98 | ||
|
|
76b1b951c0 | ||
|
|
996054b17a | ||
|
|
7fca3d4e3f | ||
|
|
c4e599c861 | ||
|
|
0f6ff2cc1e | ||
|
|
7cac4c71fb | ||
|
|
1322bdab92 | ||
|
|
f201df606a | ||
|
|
a56fce86b1 | ||
|
|
41ccc5fdd9 | ||
|
|
b2877bd493 | ||
|
|
df8f8893e7 | ||
|
|
27fbdf193b | ||
|
|
6ae892989d | ||
|
|
39a7b332da | ||
|
|
c81794b542 | ||
|
|
e456da846a | ||
|
|
5c144be05b | ||
|
|
055669c133 | ||
|
|
4b67e13b24 | ||
|
|
f1ec3eda81 |
104
.all-contributorsrc
Normal file
104
.all-contributorsrc
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"projectName": "core",
|
||||
"projectOwner": "sasjs",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 100,
|
||||
"commit": false,
|
||||
"commitConvention": "angular",
|
||||
"contributors": [
|
||||
{
|
||||
"login": "allanbowe",
|
||||
"name": "Allan Bowe",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4420615?v=4",
|
||||
"profile": "https://github.com/allanbowe",
|
||||
"contributions": [
|
||||
"business",
|
||||
"code",
|
||||
"content",
|
||||
"doc",
|
||||
"infra",
|
||||
"maintenance",
|
||||
"mentoring",
|
||||
"question",
|
||||
"review",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rafgag",
|
||||
"name": "rafgag",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/69139928?v=4",
|
||||
"profile": "https://github.com/rafgag",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tmoody",
|
||||
"name": "Trevor Moody",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/79837106?v=4",
|
||||
"profile": "https://github.com/tmoody",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "krishna-acondy",
|
||||
"name": "Krishna Acondy",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2980428?v=4",
|
||||
"profile": "https://krishna-acondy.io/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"infra",
|
||||
"blog",
|
||||
"content",
|
||||
"ideas",
|
||||
"video"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "saadjutt01",
|
||||
"name": "Muhammad Saad ",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/8914650?v=4",
|
||||
"profile": "https://github.com/saadjutt01",
|
||||
"contributions": [
|
||||
"code",
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "YuryShkoda",
|
||||
"name": "Yury Shkoda",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/25773492?v=4",
|
||||
"profile": "https://www.erudicat.com/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"infra",
|
||||
"video"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "medjedovicm",
|
||||
"name": "Mihajlo Medjedovic",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/18329105?v=4",
|
||||
"profile": "https://github.com/medjedovicm",
|
||||
"contributions": [
|
||||
"infra"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kkchandok",
|
||||
"name": "kkchandok",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/46090627?v=4",
|
||||
"profile": "https://github.com/kkchandok",
|
||||
"contributions": [
|
||||
"ideas"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7
|
||||
}
|
||||
18
.git-hooks/commit-msg
Executable file
18
.git-hooks/commit-msg
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
RED="\033[1;31m"
|
||||
GREEN="\033[1;32m"
|
||||
|
||||
# Get the commit message (the parameter we're given is just the path to the
|
||||
# temporary file which holds the message).
|
||||
commit_message=$(cat "$1")
|
||||
|
||||
if (echo "$commit_message" | grep -Eq "^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z \-]+\))?!?: .+$") then
|
||||
echo "${GREEN} ✔ Commit message meets Conventional Commit standards"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "${RED}❌ Commit message does not meet the Conventional Commit standard!"
|
||||
echo "An example of a valid message is:"
|
||||
echo " feat(login): add the 'remember me' button"
|
||||
echo "ℹ More details at: https://www.conventionalcommits.org/en/v1.0.0/#summary"
|
||||
exit 1
|
||||
2
.git-hooks/pre-commit
Executable file
2
.git-hooks/pre-commit
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
sasjs lint
|
||||
30
.github/vpn/config.ovpn
vendored
Normal file
30
.github/vpn/config.ovpn
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
cipher AES-256-CBC
|
||||
setenv FORWARD_COMPATIBLE 1
|
||||
client
|
||||
server-poll-timeout 4
|
||||
nobind
|
||||
remote vpn.analytium.co.uk 1194 udp
|
||||
remote vpn.analytium.co.uk 1194 udp
|
||||
remote vpn.analytium.co.uk 443 tcp
|
||||
remote vpn.analytium.co.uk 1194 udp
|
||||
remote vpn.analytium.co.uk 1194 udp
|
||||
remote vpn.analytium.co.uk 1194 udp
|
||||
remote vpn.analytium.co.uk 1194 udp
|
||||
remote vpn.analytium.co.uk 1194 udp
|
||||
dev tun
|
||||
dev-type tun
|
||||
ns-cert-type server
|
||||
setenv opt tls-version-min 1.0 or-highest
|
||||
reneg-sec 604800
|
||||
sndbuf 0
|
||||
rcvbuf 0
|
||||
# NOTE: LZO commands are pushed by the Access Server at connect time.
|
||||
# NOTE: The below line doesn't disable LZO.
|
||||
comp-lzo no
|
||||
verb 3
|
||||
setenv PUSH_PEER_INFO
|
||||
|
||||
ca ca.crt
|
||||
cert user.crt
|
||||
key user.key
|
||||
tls-auth tls.key 1
|
||||
84
.github/workflows/run-tests.yml
vendored
Normal file
84
.github/workflows/run-tests.yml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Node.js CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Write VPN Files
|
||||
run: |
|
||||
echo "$CA_CRT" > .github/vpn/ca.crt
|
||||
echo "$USER_CRT" > .github/vpn/user.crt
|
||||
echo "$USER_KEY" > .github/vpn/user.key
|
||||
echo "$TLS_KEY" > .github/vpn/tls.key
|
||||
shell: bash
|
||||
env:
|
||||
CA_CRT: ${{ secrets.CA_CRT}}
|
||||
USER_CRT: ${{ secrets.USER_CRT }}
|
||||
USER_KEY: ${{ secrets.USER_KEY }}
|
||||
TLS_KEY: ${{ secrets.TLS_KEY }}
|
||||
|
||||
- name: Install Open VPN
|
||||
run: |
|
||||
sudo apt install apt-transport-https
|
||||
sudo wget https://swupdate.openvpn.net/repos/openvpn-repo-pkg-key.pub
|
||||
sudo apt-key add openvpn-repo-pkg-key.pub
|
||||
sudo wget -O /etc/apt/sources.list.d/openvpn3.list https://swupdate.openvpn.net/community/openvpn3/repos/openvpn3-bionic.list
|
||||
sudo apt update
|
||||
sudo apt install openvpn3
|
||||
|
||||
- name: Start Open VPN 3
|
||||
run: openvpn3 session-start --config .github/vpn/config.ovpn
|
||||
|
||||
- name: Install Doxygen
|
||||
run: sudo apt-get install doxygen
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Check code style
|
||||
run: npm run lint
|
||||
|
||||
- name: Add client
|
||||
run: echo "CLIENT=${{secrets.CLIENT}}"> .env.viya
|
||||
|
||||
- name: Add secret
|
||||
run: echo "SECRET=${{secrets.SECRET}}" >> .env.viya
|
||||
|
||||
- name: Add access token
|
||||
run: echo "ACCESS_TOKEN=${{secrets.ACCESS_TOKEN}}" >> .env.viya
|
||||
|
||||
- name: Add refresh token
|
||||
run: echo "REFRESH_TOKEN=${{secrets.REFRESH_TOKEN}}" >> .env.viya
|
||||
|
||||
- name: Build Project
|
||||
run: npm run build
|
||||
|
||||
- name: Run SASjs tests
|
||||
run: npm run test
|
||||
env:
|
||||
CI: true
|
||||
CLIENT: ${{secrets.CLIENT}}
|
||||
SECRET: ${{secrets.SECRET}}
|
||||
SAS_USERNAME: ${{secrets.SAS_USERNAME}}
|
||||
SAS_PASSWORD: ${{secrets.SAS_PASSWORD}}
|
||||
SERVER_URL: ${{secrets.SERVER_URL}}
|
||||
SERVER_TYPE: ${{secrets.SERVER_TYPE}}
|
||||
ACCESS_TOKEN: ${{secrets.ACCESS_TOKEN}}
|
||||
REFRESH_TOKEN: ${{secrets.REFRESH_TOKEN}}
|
||||
@@ -1,5 +1,5 @@
|
||||
tasks:
|
||||
- init: npm i -g @sasjs/cli
|
||||
- init: nvm install --latest-npm && npm i -g @sasjs/cli
|
||||
|
||||
image:
|
||||
file: .gitpod.dockerfile
|
||||
|
||||
@@ -3,8 +3,9 @@ build.py
|
||||
.gitpod*
|
||||
tests/
|
||||
sasjs/
|
||||
.vscode/
|
||||
.github/
|
||||
.git-hooks/
|
||||
.vscode/
|
||||
main.dox
|
||||
make_singlefile.sh
|
||||
*.md
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
"noTrailingSpaces": true,
|
||||
"noEncodedPasswords": true,
|
||||
"hasDoxygenHeader": true,
|
||||
"hasMacroNameInMend": false,
|
||||
"hasMacroNameInMend": true,
|
||||
"hasMacroParentheses": true,
|
||||
"noNestedMacros": false,
|
||||
"noSpacesInFileNames": true,
|
||||
"maxLineLength": 135,
|
||||
"maxLineLength": 230,
|
||||
"lowerCaseFileNames": true,
|
||||
"noTabIndentation": true,
|
||||
"indentationMultiple": 2
|
||||
|
||||
63
README.md
63
README.md
@@ -1,6 +1,25 @@
|
||||
[](/LICENSE) [](/package.json)   [](https://gitpod.io/#https://github.com/sasjs/core)
|
||||
|
||||
# Macro Core
|
||||
[![npm package][npm-image]][npm-url]
|
||||
[![Github Workflow][githubworkflow-image]][githubworkflow-url]
|
||||
[![Dependency Status][dependency-image]][dependency-url]
|
||||
[]()
|
||||

|
||||
[](/LICENSE)
|
||||

|
||||
[](https://github.com/sasjs/core/issues?q=is%3Aissue+is%3Aclosed)
|
||||
[](https://github.com/sasjs/core/issues)
|
||||

|
||||
[](https://gitpod.io/#https://github.com/sasjs/core)
|
||||
|
||||
|
||||
[npm-image]:https://img.shields.io/npm/v/@sasjs/core.svg
|
||||
[npm-url]:http://npmjs.org/package/@sasjs/core
|
||||
[githubworkflow-image]:https://github.com/sasjs/core/actions/workflows/main.yml/badge.svg
|
||||
[githubworkflow-url]:https://github.com/sasjs/core/blob/main/.github/workflows/main.yml
|
||||
[dependency-image]:https://david-dm.org/sasjs/core.svg
|
||||
[dependency-url]:https://github.com/sasjs/core/blob/main/package.json
|
||||
|
||||
|
||||
|
||||
Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/CONTRIBUTING.md) are welcomed.
|
||||
|
||||
@@ -151,3 +170,43 @@ When contributing to this library, it is therefore important to ensure that all
|
||||
# General Notes
|
||||
|
||||
- All macros should be compatible with SAS versions from support level B and above (so currently 9.2 and later). If an earlier version is not supported, then the macro should say as such in the header documentation, and exit gracefully (eg `%if %sysevalf(&sysver<9.3) %then %return`).
|
||||
|
||||
## Star Gazing
|
||||
|
||||
If you find this library useful, please leave a [star](https://github.com/sasjs/core/stargazers) and help us grow our star graph!
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
## Contributors ✨
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/allanbowe"><img src="https://avatars.githubusercontent.com/u/4420615?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Allan Bowe</b></sub></a><br /><a href="#business-allanbowe" title="Business development">💼</a> <a href="https://github.com/sasjs/core/commits?author=allanbowe" title="Code">💻</a> <a href="#content-allanbowe" title="Content">🖋</a> <a href="https://github.com/sasjs/core/commits?author=allanbowe" title="Documentation">📖</a> <a href="#infra-allanbowe" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-allanbowe" title="Maintenance">🚧</a> <a href="#mentoring-allanbowe" title="Mentoring">🧑🏫</a> <a href="#question-allanbowe" title="Answering Questions">💬</a> <a href="https://github.com/sasjs/core/pulls?q=is%3Apr+reviewed-by%3Aallanbowe" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sasjs/core/commits?author=allanbowe" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/rafgag"><img src="https://avatars.githubusercontent.com/u/69139928?v=4?s=100" width="100px;" alt=""/><br /><sub><b>rafgag</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=rafgag" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/tmoody"><img src="https://avatars.githubusercontent.com/u/79837106?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Trevor Moody</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=tmoody" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://krishna-acondy.io/"><img src="https://avatars.githubusercontent.com/u/2980428?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Krishna Acondy</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=krishna-acondy" title="Code">💻</a> <a href="#infra-krishna-acondy" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#blog-krishna-acondy" title="Blogposts">📝</a> <a href="#content-krishna-acondy" title="Content">🖋</a> <a href="#ideas-krishna-acondy" title="Ideas, Planning, & Feedback">🤔</a> <a href="#video-krishna-acondy" title="Videos">📹</a></td>
|
||||
<td align="center"><a href="https://github.com/saadjutt01"><img src="https://avatars.githubusercontent.com/u/8914650?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Muhammad Saad </b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=saadjutt01" title="Code">💻</a> <a href="#ideas-saadjutt01" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://www.erudicat.com/"><img src="https://avatars.githubusercontent.com/u/25773492?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yury Shkoda</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=YuryShkoda" title="Code">💻</a> <a href="#infra-YuryShkoda" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#video-YuryShkoda" title="Videos">📹</a></td>
|
||||
<td align="center"><a href="https://github.com/medjedovicm"><img src="https://avatars.githubusercontent.com/u/18329105?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mihajlo Medjedovic</b></sub></a><br /><a href="#infra-medjedovicm" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kkchandok"><img src="https://avatars.githubusercontent.com/u/46090627?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kkchandok</b></sub></a><br /><a href="#ideas-kkchandok" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
18
SECURITY.md
Normal file
18
SECURITY.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Security Policy
|
||||
|
||||
Security is an extremely high priority when it comes to the SASjs product suite. We take a number of steps across all repositories to minimise risk, such as:
|
||||
|
||||
* Regular dependabot updates
|
||||
* Snyk reports
|
||||
* Minimising dependencies, especially production dependencies (sasjs/core has NONE)
|
||||
* Testing & Code review process
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We support only the latest version
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We welcome disclosures of all kinds in relation to all the SASjs libraries. You can submit them here: [https://sasapps.io/contact-us](https://sasapps.io/contact-us)
|
||||
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/**
|
||||
@file
|
||||
@brief to be deprecated
|
||||
@details We will deprecate this macro in 2022
|
||||
@brief Abort, ungracefully
|
||||
@details Will abort with a straightforward %abort if the condition is true.
|
||||
|
||||
As you can see, it's not a macro function.
|
||||
|
||||
Use mp_abort.sas instead.
|
||||
<h4> Related Macros </h4>
|
||||
@li mp_abort.sas
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
@cond
|
||||
**/
|
||||
|
||||
%macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1)
|
||||
%macro mf_abort(mac=mf_abort.sas, type=deprecated, msg=, iftrue=%str(1=1)
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%if not(%eval(%unquote(&iftrue))) %then %return;
|
||||
@@ -21,116 +20,8 @@
|
||||
%if %length(&mac)>0 %then %put NOTE- called by &mac;
|
||||
%put NOTE - &msg;
|
||||
|
||||
/* Stored Process Server web app context */
|
||||
%if %symexist(_metaperson) or "&SYSPROCESSNAME"="Compute Server" %then %do;
|
||||
options obs=max replace nosyntaxcheck mprint;
|
||||
/* extract log err / warn, if exist */
|
||||
%local logloc logline;
|
||||
%global logmsg; /* capture global messages */
|
||||
%if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
|
||||
%else %let logloc=%qsysfunc(getoption(LOG));
|
||||
proc printto log=log;run;
|
||||
%if %length(&logloc)>0 %then %do;
|
||||
%let logline=0;
|
||||
data _null_;
|
||||
infile &logloc lrecl=5000;
|
||||
input; putlog _infile_;
|
||||
i=1;
|
||||
retain logonce 0;
|
||||
if (
|
||||
_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR"
|
||||
) and logonce=0
|
||||
then do;
|
||||
call symputx('logline',_n_);
|
||||
logonce+1;
|
||||
end;
|
||||
run;
|
||||
/* capture log including lines BEFORE the err */
|
||||
%if &logline>0 %then %do;
|
||||
data _null_;
|
||||
infile &logloc lrecl=5000;
|
||||
input;
|
||||
i=1;
|
||||
stoploop=0;
|
||||
if _n_ ge &logline-5 and stoploop=0 then do until (i>12);
|
||||
call symputx('logmsg',catx('\n',symget('logmsg'),_infile_));
|
||||
input;
|
||||
i+1;
|
||||
stoploop=1;
|
||||
end;
|
||||
if stoploop=1 then stop;
|
||||
run;
|
||||
%end;
|
||||
%end;
|
||||
%abort;
|
||||
|
||||
/* send response in SASjs JSON format */
|
||||
data _null_;
|
||||
file _webout mod lrecl=32000;
|
||||
length msg $32767;
|
||||
sasdatetime=datetime();
|
||||
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
|
||||
/* escape the quotes */
|
||||
msg=tranwrd(msg,'"','\"');
|
||||
/* ditch the CRLFs as chrome complains */
|
||||
msg=compress(msg,,'kw');
|
||||
/* quote without quoting the quotes (which are escaped instead) */
|
||||
msg=cats('"',msg,'"');
|
||||
if symexist('_debug') then debug=symget('_debug');
|
||||
if debug ge 131 then put '>>weboutBEGIN<<';
|
||||
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
|
||||
put ',"sasjsAbort" : [{';
|
||||
put ' "MSG":' msg ;
|
||||
put ' ,"MAC": "' "&mac" '"}]';
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
if symexist('_metauser') then do;
|
||||
_METAUSER=quote(trim(symget('_METAUSER')));
|
||||
put ",""_METAUSER"": " _METAUSER;
|
||||
_METAPERSON=quote(trim(symget('_METAPERSON')));
|
||||
put ',"_METAPERSON": ' _METAPERSON;
|
||||
end;
|
||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||
put ",""SYSCC"" : ""&syscc"" ";
|
||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
||||
put "}" @;
|
||||
%if &_debug ge 131 %then %do;
|
||||
put '>>weboutEND<<';
|
||||
%end;
|
||||
run;
|
||||
%let syscc=0;
|
||||
%if %symexist(SYS_JES_JOB_URI) %then %do;
|
||||
/* refer web service output to file service in one hit */
|
||||
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
|
||||
name="_webout.json";
|
||||
%let rc=%sysfunc(fcopy(_web,_webout));
|
||||
%end;
|
||||
%else %do;
|
||||
data _null_;
|
||||
if symexist('sysprocessmode')
|
||||
then if symget("sysprocessmode")="SAS Stored Process Server"
|
||||
then rc=stpsrvset('program error', 0);
|
||||
run;
|
||||
%end;
|
||||
/**
|
||||
* endsas is reliable but kills some deployments.
|
||||
* Abort variants are ungraceful (non zero return code)
|
||||
* This approach lets SAS run silently until the end :-)
|
||||
*/
|
||||
%put _all_;
|
||||
filename skip temp;
|
||||
data _null_;
|
||||
file skip;
|
||||
put '%macro skip(); %macro skippy();';
|
||||
run;
|
||||
%inc skip;
|
||||
%end;
|
||||
%else %do;
|
||||
%put _all_;
|
||||
%abort cancel;
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_abort;
|
||||
|
||||
/** @endcond */
|
||||
@@ -23,4 +23,4 @@
|
||||
%if %sysfunc(exist(&libds)) ne 1 & %sysfunc(exist(&libds,VIEW)) ne 1 %then 0;
|
||||
%else 1;
|
||||
|
||||
%mend;
|
||||
%mend mf_existds;
|
||||
|
||||
@@ -42,6 +42,6 @@
|
||||
-1
|
||||
%put &sysmacroname: &feature not found;
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_existfeature;
|
||||
|
||||
/** @endcond */
|
||||
@@ -24,4 +24,4 @@
|
||||
0
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mf_existfileref;
|
||||
@@ -30,6 +30,6 @@
|
||||
%let rc=%sysfunc(close(&dsid));
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mf_existvar;
|
||||
|
||||
/** @endcond */
|
||||
@@ -54,6 +54,6 @@
|
||||
0
|
||||
%put Vars not found: &found;
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_existvarlist;
|
||||
|
||||
/** @endcond */
|
||||
@@ -31,4 +31,4 @@
|
||||
%sysfunc(attrc(&dsid,&attr))
|
||||
%let rc=%sysfunc(close(&dsid));
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_getattrc;
|
||||
@@ -31,4 +31,4 @@
|
||||
%sysfunc(attrn(&dsid,&attr))
|
||||
%let rc=%sysfunc(close(&dsid));
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_getattrn;
|
||||
@@ -48,6 +48,6 @@
|
||||
|
||||
&engine
|
||||
|
||||
%mend;
|
||||
%mend mf_getengine;
|
||||
|
||||
/** @endcond */
|
||||
@@ -44,4 +44,4 @@
|
||||
%sysfunc(INPUTN(&bytes, best.),sizekmg.)
|
||||
%end;
|
||||
|
||||
%mend ;
|
||||
%mend mf_getfilesize ;
|
||||
@@ -29,4 +29,4 @@
|
||||
&valc
|
||||
%end;
|
||||
%else %put %str(ERR)OR: Unable to find key &key in ds &libds;
|
||||
%mend;
|
||||
%mend mf_getkeyvalue;
|
||||
@@ -62,4 +62,4 @@
|
||||
%else %if &switch=VIYARESTAPI %then %do;
|
||||
%mf_trimstr(%sysfunc(getoption(servicesbaseurl)),/)
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_getplatform;
|
||||
@@ -50,4 +50,4 @@
|
||||
|
||||
&buffer
|
||||
|
||||
%mend;
|
||||
%mend mf_getquotedstr;
|
||||
@@ -38,6 +38,6 @@
|
||||
|
||||
&schema
|
||||
|
||||
%mend;
|
||||
%mend mf_getschema;
|
||||
|
||||
/** @endcond */
|
||||
|
||||
@@ -34,4 +34,4 @@
|
||||
%end;
|
||||
%end;
|
||||
%put unable to find available fileref in range &prefix.0-&maxtries;
|
||||
%mend;
|
||||
%mend mf_getuniquefileref;
|
||||
@@ -37,4 +37,4 @@
|
||||
%end;
|
||||
%end;
|
||||
%put unable to find available libref in range &prefix.0-&maxtries;
|
||||
%mend;
|
||||
%mend mf_getuniquelibref;
|
||||
@@ -39,4 +39,4 @@
|
||||
|
||||
%quote(&user)
|
||||
|
||||
%mend;
|
||||
%mend mf_getuser;
|
||||
|
||||
@@ -30,4 +30,4 @@
|
||||
%trim(&&&variable)
|
||||
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_getvalue;
|
||||
@@ -29,4 +29,4 @@
|
||||
%let rc=%sysfunc(close(&dsid));
|
||||
%end;
|
||||
&nvars
|
||||
%mend;
|
||||
%mend mf_getvarcount;
|
||||
@@ -49,4 +49,4 @@
|
||||
%let rc = %sysfunc(close(&dsid));
|
||||
/* Return variable format */
|
||||
&vlen
|
||||
%mend;
|
||||
%mend mf_getVarLen;
|
||||
@@ -66,7 +66,8 @@
|
||||
%let rc=%sysfunc(close(&dsid));
|
||||
%end;
|
||||
%else %do;
|
||||
%put unable to open &libds (rc=&dsid);
|
||||
%put &sysmacroname: Unable to open &libds (rc=&dsid);
|
||||
%put &sysmacroname: SYSMSG= %sysfunc(sysmsg());
|
||||
%let rc=%sysfunc(close(&dsid));
|
||||
%end;
|
||||
&outvar
|
||||
|
||||
@@ -51,4 +51,4 @@ returns:
|
||||
/* Return variable number */
|
||||
&vnum.
|
||||
|
||||
%mend;
|
||||
%mend mf_getVarNum;
|
||||
@@ -40,4 +40,4 @@
|
||||
|
||||
&engine
|
||||
|
||||
%mend;
|
||||
%mend mf_getxengine;
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
|
||||
%sysevalf(%superq(param)=,boolean)
|
||||
|
||||
%mend;
|
||||
%mend mf_isblank;
|
||||
@@ -31,4 +31,4 @@
|
||||
|
||||
&is_directory
|
||||
|
||||
%mend;
|
||||
%mend mf_isdir;
|
||||
@@ -26,4 +26,4 @@
|
||||
&root
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mf_loc;
|
||||
|
||||
@@ -64,4 +64,4 @@ Usage:
|
||||
%end;
|
||||
%end;
|
||||
/* exit quietly if directory did exist.*/
|
||||
%mend;
|
||||
%mend mf_mkdir;
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
%if %symexist(&var) %then %do;
|
||||
%superq(&var)
|
||||
%end;
|
||||
%mend;
|
||||
%mend mf_mval;
|
||||
|
||||
@@ -23,4 +23,4 @@
|
||||
%macro mf_nobs(libds
|
||||
)/*/STORE SOURCE*/;
|
||||
%mf_getattrn(&libds,NLOBS)
|
||||
%mend;
|
||||
%mend mf_nobs;
|
||||
@@ -47,4 +47,4 @@
|
||||
&basestr
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mf_trimstr;
|
||||
@@ -62,4 +62,4 @@
|
||||
%else %mf_abort(mac=mf_verifymacvars,type=&mabort,msg=&abortmsg);
|
||||
%exit_success:
|
||||
|
||||
%mend;
|
||||
%mend mf_verifymacvars;
|
||||
|
||||
@@ -50,5 +50,5 @@
|
||||
|
||||
&outvar
|
||||
|
||||
%mend;
|
||||
%mend mf_wordsInStr1ButNotStr2;
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
|
||||
/* send response in SASjs JSON format */
|
||||
data _null_;
|
||||
file _webout mod lrecl=32000;
|
||||
file _webout mod lrecl=32000 encoding='utf-8';
|
||||
length msg $32767 debug $8;
|
||||
sasdatetime=datetime();
|
||||
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
|
||||
@@ -133,6 +133,8 @@
|
||||
put ",""SYSCC"" : ""&syscc"" ";
|
||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||
sysvlong=quote(trim(symget('sysvlong')));
|
||||
put ',"SYSVLONG" : ' sysvlong;
|
||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
||||
put "}" @;
|
||||
@@ -163,6 +165,7 @@
|
||||
sysuserid=symget('sysuserid');
|
||||
iftrue=symget('iftrue');
|
||||
put (_all_)(/=);
|
||||
call symputx('syscc',0);
|
||||
abort cancel nolist;
|
||||
run;
|
||||
%end;
|
||||
|
||||
@@ -142,4 +142,4 @@
|
||||
proc sql;
|
||||
drop table &ds;
|
||||
|
||||
%mend;
|
||||
%mend mp_assertcols;
|
||||
@@ -144,4 +144,4 @@
|
||||
proc sql;
|
||||
drop table &ds;
|
||||
|
||||
%mend;
|
||||
%mend mp_assertcolvals;
|
||||
117
base/mp_base64copy.sas
Normal file
117
base/mp_base64copy.sas
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
@file
|
||||
@brief Convert a file to/from base64 format
|
||||
@details Creates a new version of a file either encoded or decoded using
|
||||
Base64. Inspired by this post by Michael Dixon:
|
||||
https://support.selerity.com.au/hc/en-us/articles/223345708-Tip-SAS-and-Base64
|
||||
|
||||
Usage:
|
||||
|
||||
filename tmp temp;
|
||||
data _null_;
|
||||
file tmp;
|
||||
put 'base ik ally';
|
||||
run;
|
||||
%mp_base64copy(inref=tmp, outref=myref, action=ENCODE)
|
||||
|
||||
data _null_;
|
||||
infile myref;
|
||||
input;
|
||||
put _infile_;
|
||||
run;
|
||||
|
||||
%mp_base64copy(inref=myref, outref=mynewref, action=DECODE)
|
||||
|
||||
data _null_;
|
||||
infile mynewref;
|
||||
input;
|
||||
put _infile_;
|
||||
run;
|
||||
|
||||
@param [in] inref= Fileref of the input file (should exist)
|
||||
@param [out] outref= Output fileref. If it does not exist, it is created.
|
||||
@param [in] action= (ENCODE) The action to take. Valid values:
|
||||
@li ENCODE - Convert the file to base64 format
|
||||
@li DECODE - Decode the file from base64 format
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_abort.sas
|
||||
|
||||
|
||||
**/
|
||||
|
||||
%macro mp_base64copy(
|
||||
inref=0,
|
||||
outref=0,
|
||||
action=ENCODE
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%let inref=%upcase(&inref);
|
||||
%let outref=%upcase(&outref);
|
||||
%let action=%upcase(&action);
|
||||
%local infound outfound;
|
||||
%let infound=0;
|
||||
%let outfound=0;
|
||||
data _null_;
|
||||
set sashelp.vextfl(where=(fileref="&inref" or fileref="&outref"));
|
||||
if fileref="&inref" then call symputx('infound',1,'l');
|
||||
if fileref="&outref" then call symputx('outfound',1,'l');
|
||||
run;
|
||||
|
||||
%mp_abort(iftrue= (&infound=0)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(INREF &inref NOT FOUND!)
|
||||
)
|
||||
%mp_abort(iftrue= (&outref=0)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(OUTREF NOT PROVIDED!)
|
||||
)
|
||||
%mp_abort(iftrue= (&action ne ENCODE and &action ne DECODE)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(Invalid action! Should be ENCODE OR DECODE)
|
||||
)
|
||||
|
||||
%if &outfound=0 %then %do;
|
||||
filename &outref temp lrecl=2097088;
|
||||
%end;
|
||||
|
||||
%if &action=ENCODE %then %do;
|
||||
data _null_;
|
||||
length b64 $ 76 line $ 57;
|
||||
retain line "";
|
||||
infile &inref recfm=F lrecl= 1 end=eof;
|
||||
input @1 stream $char1.;
|
||||
file &outref recfm=N;
|
||||
substr(line,(_N_-(CEIL(_N_/57)-1)*57),1) = byte(rank(stream));
|
||||
if mod(_N_,57)=0 or EOF then do;
|
||||
if eof then b64=put(trim(line),$base64X76.);
|
||||
else b64=put(line, $base64X76.);
|
||||
put b64 + (-1) @;
|
||||
line="";
|
||||
end;
|
||||
run;
|
||||
%end;
|
||||
%else %if &action=DECODE %then %do;
|
||||
data _null_;
|
||||
length filein 8 fileout 8;
|
||||
filein = fopen("&inref",'I',4,'B');
|
||||
fileout = fopen("&outref",'O',3,'B');
|
||||
char= '20'x;
|
||||
do while(fread(filein)=0);
|
||||
length raw $4;
|
||||
do i=1 to 4;
|
||||
rc=fget(filein,char,1);
|
||||
substr(raw,i,1)=char;
|
||||
end;
|
||||
rc = fput(fileout,input(raw,$base64X4.));
|
||||
rc = fwrite(fileout);
|
||||
end;
|
||||
rc = fclose(filein);
|
||||
rc = fclose(fileout);
|
||||
run;
|
||||
%end;
|
||||
|
||||
%mend mp_base64copy;
|
||||
@@ -53,4 +53,4 @@
|
||||
%if &outref=____out %then %do;
|
||||
filename &outref clear;
|
||||
%end;
|
||||
%mend;
|
||||
%mend mp_binarycopy;
|
||||
@@ -67,5 +67,5 @@
|
||||
else put inchar $char1.;
|
||||
end;
|
||||
run;
|
||||
%mend;
|
||||
%mend mp_cleancsv;
|
||||
/** @endcond */
|
||||
@@ -64,4 +64,4 @@ data &outds;
|
||||
output;
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_createconstraints;
|
||||
@@ -80,4 +80,4 @@ Usage:
|
||||
)
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_createwebservice;
|
||||
|
||||
@@ -141,4 +141,4 @@ data &outds
|
||||
%end;
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_csv2ds;
|
||||
@@ -49,4 +49,4 @@ data &outds;
|
||||
end;
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_deleteconstraints;
|
||||
@@ -167,4 +167,4 @@ run;
|
||||
by filepath file_or_folder filename ext ;
|
||||
run;
|
||||
%end;
|
||||
%mend;
|
||||
%mend mp_dirlist;
|
||||
@@ -47,4 +47,4 @@
|
||||
%end;
|
||||
as &outvar length=&varlen
|
||||
from &libds;
|
||||
%mend;
|
||||
%mend mp_distinctfmtvalues;
|
||||
@@ -251,4 +251,4 @@ quit;
|
||||
%put NOTE-;%put NOTE-;
|
||||
%put NOTE- %sysfunc(dequote(&cards_file.));
|
||||
%put NOTE-;%put NOTE-;
|
||||
%mend;
|
||||
%mend mp_ds2cards;
|
||||
@@ -55,4 +55,4 @@ data _null_;
|
||||
run;
|
||||
|
||||
|
||||
%mend;
|
||||
%mend mp_ds2csv;
|
||||
168
base/mp_ds2inserts.sas
Normal file
168
base/mp_ds2inserts.sas
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
@file
|
||||
@brief Export a dataset to SQL insert statements
|
||||
@details Converts dataset values to SQL insert statements for use across
|
||||
multiple database types.
|
||||
|
||||
Usage:
|
||||
|
||||
%mp_ds2inserts(sashelp.class,outref=myref,outds=class)
|
||||
data class;
|
||||
set sashelp.class;
|
||||
stop;
|
||||
proc sql;
|
||||
%inc myref;
|
||||
|
||||
@param [in] ds The dataset to be exported
|
||||
@param [in] maxobs= (max) The max number of inserts to create
|
||||
@param [out] outref= (0) The output fileref. If it does not exist, it is
|
||||
created. If it does exist, new records are APPENDED.
|
||||
@param [out] schema= (0) The library (or schema) in which the target table is
|
||||
located. If not provided, is ignored.
|
||||
@param [out] outds= (0) The output table to load. If not provided, will
|
||||
default to the table in the &ds parameter.
|
||||
@param [in] flavour= (SAS) The SQL flavour to be applied to the output. Valid
|
||||
options:
|
||||
@li SAS (default) - suitable for regular proc sql
|
||||
@li PGSQL - Used for Postgres databases
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_existfileref.sas
|
||||
@li mf_getvarcount.sas
|
||||
@li mf_getvarlist.sas
|
||||
@li mf_getvartype.sas
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe (credit mjsq)
|
||||
**/
|
||||
|
||||
%macro mp_ds2inserts(ds, outref=0,schema=0,outds=0,flavour=SAS,maxobs=max
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%if not %sysfunc(exist(&ds)) %then %do;
|
||||
%put %str(WAR)NING: &ds does not exist;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%if not %sysfunc(exist(&ds)) %then %do;
|
||||
%put %str(WAR)NING: &ds does not exist;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%if %index(&ds,.)=0 %then %let ds=WORK.&ds;
|
||||
|
||||
%let flavour=%upcase(&flavour);
|
||||
%if &flavour ne SAS and &flavour ne PGSQL %then %do;
|
||||
%put %str(WAR)NING: &flavour is not supported;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%if &outref=0 %then %do;
|
||||
%put %str(WAR)NING: Please provide a fileref;
|
||||
%return;
|
||||
%end;
|
||||
%if %mf_existfileref(&outref)=0 %then %do;
|
||||
filename &outref temp lrecl=66000;
|
||||
%end;
|
||||
|
||||
%if &schema=0 %then %let schema=;
|
||||
%else %let schema=&schema..;
|
||||
|
||||
%if &outds=0 %then %let outds=%scan(&ds,2,.);
|
||||
|
||||
%local nobs;
|
||||
proc sql noprint;
|
||||
select count(*) into: nobs TRIMMED from &ds;
|
||||
%if &nobs=0 %then %do;
|
||||
data _null_;
|
||||
file &outref mod;
|
||||
put "/* No rows found in &ds */";
|
||||
run;
|
||||
%end;
|
||||
|
||||
%local vars;
|
||||
%let vars=%mf_getvarcount(&ds);
|
||||
%if &vars=0 %then %do;
|
||||
data _null_;
|
||||
file &outref mod;
|
||||
put "/* No columns found in &schema.&ds */";
|
||||
run;
|
||||
%return;
|
||||
%end;
|
||||
%else %if &vars>1600 and &flavour=PGSQL %then %do;
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
put "/* &schema.&ds contains &vars vars */";
|
||||
put "/* Postgres cannot handle tables with over 1600 vars */";
|
||||
put "/* No inserts will be generated for this table */";
|
||||
run;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%local varlist varlistcomma;
|
||||
%let varlist=%mf_getvarlist(&ds);
|
||||
%let varlistcomma=%mf_getvarlist(&ds,dlm=%str(,),quote=double);
|
||||
|
||||
/* next, export data */
|
||||
data _null_;
|
||||
file &outref mod ;
|
||||
if _n_=1 then put "/* &schema.&outds (&nobs rows, &vars columns) */";
|
||||
set &ds;
|
||||
%if &maxobs ne max %then %do;
|
||||
if _n_>&maxobs then stop;
|
||||
%end;
|
||||
length _____str $32767;
|
||||
format _numeric_ best.;
|
||||
format _character_ ;
|
||||
%local i comma var vtype;
|
||||
%do i=1 %to %sysfunc(countw(&varlist));
|
||||
%let var=%scan(&varlist,&i);
|
||||
%let vtype=%mf_getvartype(&ds,&var);
|
||||
%if &i=1 %then %do;
|
||||
%if &flavour=SAS %then %do;
|
||||
put "insert into &schema.&outds set ";
|
||||
put " &var="@;
|
||||
%end;
|
||||
%else %if &flavour=PGSQL %then %do;
|
||||
_____str=cats(
|
||||
"INSERT INTO &schema.&outds ("
|
||||
,symget('varlistcomma')
|
||||
,") VALUES ("
|
||||
);
|
||||
put _____str;
|
||||
put " "@;
|
||||
%end;
|
||||
%end;
|
||||
%else %do;
|
||||
%if &flavour=SAS %then %do;
|
||||
put " ,&var="@;
|
||||
%end;
|
||||
%else %if &flavour=PGSQL %then %do;
|
||||
put " ,"@;
|
||||
%end;
|
||||
%end;
|
||||
%if &vtype=N %then %do;
|
||||
%if &flavour=SAS %then %do;
|
||||
put &var;
|
||||
%end;
|
||||
%else %if &flavour=PGSQL %then %do;
|
||||
if missing(&var) then put 'NULL';
|
||||
else put &var;
|
||||
%end;
|
||||
%end;
|
||||
%else %do;
|
||||
_____str="'"!!trim(tranwrd(&var,"'","''"))!!"'";
|
||||
put _____str;
|
||||
%end;
|
||||
%end;
|
||||
%if &flavour=SAS %then %do;
|
||||
put ';';
|
||||
%end;
|
||||
%else %if &flavour=PGSQL %then %do;
|
||||
put ');';
|
||||
%end;
|
||||
|
||||
if _n_=&nobs then put /;
|
||||
run;
|
||||
|
||||
%mend mp_ds2inserts;
|
||||
@@ -99,4 +99,4 @@ filename &outref temp;
|
||||
run;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_filtergenerate;
|
||||
|
||||
@@ -78,7 +78,8 @@ run;
|
||||
|
||||
data &outds;
|
||||
if &sqlrc or &syscc or &syserr then do;
|
||||
REASON_CD=coalescec(symget('SYSERRORTEXT'),symget('SYSWARNINGTEXT'));
|
||||
REASON_CD='VALIDATION_ERROR: '!!
|
||||
coalescec(symget('SYSERRORTEXT'),symget('SYSWARNINGTEXT'));
|
||||
output;
|
||||
end;
|
||||
else stop;
|
||||
@@ -102,4 +103,4 @@ filename &fref1 clear;
|
||||
%let syscc=1008;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_filtervalidate;
|
||||
|
||||
@@ -57,4 +57,4 @@ create table &outds as
|
||||
%end;
|
||||
;
|
||||
|
||||
%mend;
|
||||
%mend mp_getconstraints;
|
||||
@@ -332,4 +332,4 @@ run;
|
||||
run;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_getdbml;
|
||||
@@ -5,6 +5,8 @@
|
||||
to create tables in SAS or a database. The macro can be used at table or
|
||||
library level. The default behaviour is to create DDL in SAS format.
|
||||
|
||||
Note - views are not currently supported.
|
||||
|
||||
Usage:
|
||||
|
||||
data test(index=(pk=(x y)/unique /nomiss));
|
||||
@@ -16,12 +18,14 @@
|
||||
%mp_getddl(work,test,flavour=tsql,showlog=YES)
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_existfileref.sas
|
||||
@li mf_getvarcount.sas
|
||||
@li mp_getconstraints.sas
|
||||
|
||||
@param lib libref of the library to create DDL for. Should be assigned.
|
||||
@param ds dataset to create ddl for (optional)
|
||||
@param fref= the fileref to which to write the DDL. If not preassigned, will
|
||||
be assigned to TEMP.
|
||||
@param fref= the fileref to which to _append_ the DDL. If it does not exist,
|
||||
it will be created.
|
||||
@param flavour= The type of DDL to create (default=SAS). Supported=TSQL
|
||||
@param showlog= Set to YES to show the DDL in the log
|
||||
@param schema= Choose a preferred schema name (default is to use actual schema
|
||||
@@ -37,9 +41,10 @@
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
/* check fileref is assigned */
|
||||
%if %sysfunc(fileref(&fref)) > 0 %then %do;
|
||||
filename &fref temp;
|
||||
%if %mf_existfileref(&fref)=0 %then %do;
|
||||
filename &fref temp ;
|
||||
%end;
|
||||
|
||||
%if %length(&libref)=0 %then %let libref=WORK;
|
||||
%let flavour=%upcase(&flavour);
|
||||
|
||||
@@ -47,6 +52,7 @@ proc sql noprint;
|
||||
create table _data_ as
|
||||
select * from dictionary.tables
|
||||
where upcase(libname)="%upcase(&libref)"
|
||||
and memtype='DATA' /* views not currently supported */
|
||||
%if %length(&ds)>0 %then %do;
|
||||
and upcase(memname)="%upcase(&ds)"
|
||||
%end;
|
||||
@@ -115,10 +121,10 @@ create table _data_ as
|
||||
end;
|
||||
run;
|
||||
%put &=constraints_used;
|
||||
%mend;
|
||||
%mend addConst;
|
||||
|
||||
data _null_;
|
||||
file &fref;
|
||||
file &fref mod;
|
||||
put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */";
|
||||
run;
|
||||
|
||||
@@ -141,13 +147,15 @@ run;
|
||||
put "create table &libref..&curds(";
|
||||
end;
|
||||
else do;
|
||||
/* just a placeholder - we filter out views at the top */
|
||||
put "create view &libref..&curds(";
|
||||
end;
|
||||
put " "@@;
|
||||
end;
|
||||
else put " ,"@@;
|
||||
if length(format)>1 then fmt=" format="!!cats(format);
|
||||
if length(label)>1 then lab=" label="!!quote(trim(label));
|
||||
if length(label)>1 then
|
||||
lab=" label="!!cats("'",tranwrd(label,"'","''"),"'");
|
||||
if notnull='yes' then notnul=' not null';
|
||||
if type='char' then typ=cats('char(',length,')');
|
||||
else if length ne 8 then typ='num length='!!left(length);
|
||||
@@ -219,6 +227,7 @@ run;
|
||||
put "create table [&schema].[&curds](";
|
||||
end;
|
||||
else do;
|
||||
/* just a placeholder - we filter out views at the top */
|
||||
put "create view [&schema].[&curds](";
|
||||
end;
|
||||
put " "@@;
|
||||
@@ -302,71 +311,81 @@ run;
|
||||
put "CREATE SCHEMA &schema;";
|
||||
%do x=1 %to %sysfunc(countw(&dsnlist));
|
||||
%let curds=%scan(&dsnlist,&x);
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
put "/* Postgres Flavour DDL for &schema..&curds */";
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
set &colinfo (where=(upcase(memname)="&curds")) end=last;
|
||||
length fmt $32;
|
||||
if _n_=1 then do;
|
||||
if memtype='DATA' then do;
|
||||
put "CREATE TABLE &schema..&curds (";
|
||||
%local curdsvarcount;
|
||||
%let curdsvarcount=%mf_getvarcount(&libref..&curds);
|
||||
%if &curdsvarcount>1600 %then %do;
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
put "/* &libref..&curds contains &curdsvarcount vars */";
|
||||
put "/* Postgres cannot create tables with over 1600 vars */";
|
||||
put "/* No DDL will be generated for this table";
|
||||
run;
|
||||
%end;
|
||||
%else %do;
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
put "/* Postgres Flavour DDL for &schema..&curds */";
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
set &colinfo (where=(upcase(memname)="&curds")) end=last;
|
||||
length fmt $32;
|
||||
if _n_=1 then do;
|
||||
if memtype='DATA' then do;
|
||||
put "CREATE TABLE &schema..&curds (";
|
||||
end;
|
||||
else do;
|
||||
/* just a placeholder - we filter out views at the top */
|
||||
put "CREATE VIEW &schema..&curds (";
|
||||
end;
|
||||
put " "@@;
|
||||
end;
|
||||
else do;
|
||||
put "CREATE VIEW &schema..&curds (";
|
||||
end;
|
||||
put " "@@;
|
||||
end;
|
||||
else put " ,"@@;
|
||||
format=upcase(format);
|
||||
if 1=0 then; /* dummy if */
|
||||
%if &applydttm=YES %then %do;
|
||||
else if format=:'DATETIME' then fmt=' TIMESTAMP ';
|
||||
%end;
|
||||
else if type='num' then fmt=' DOUBLE PRECISION';
|
||||
else fmt='VARCHAR('!!cats(length)!!')';
|
||||
if notnull='yes' then notnul=' NOT NULL';
|
||||
/* quote column names in case they represent reserved words */
|
||||
name2=quote(trim(name));
|
||||
put name2 fmt notnul;
|
||||
run;
|
||||
else put " ,"@@;
|
||||
format=upcase(format);
|
||||
if 1=0 then; /* dummy if */
|
||||
%if &applydttm=YES %then %do;
|
||||
else if format=:'DATETIME' then fmt=' TIMESTAMP ';
|
||||
%end;
|
||||
else if type='num' then fmt=' DOUBLE PRECISION';
|
||||
else fmt='VARCHAR('!!cats(length)!!')';
|
||||
if notnull='yes' then notnul=' NOT NULL';
|
||||
/* quote column names in case they represent reserved words */
|
||||
name2=quote(trim(name));
|
||||
put name2 fmt notnul;
|
||||
run;
|
||||
|
||||
/* Extra step for data constraints */
|
||||
%addConst()
|
||||
/* Extra step for data constraints */
|
||||
%addConst()
|
||||
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
put ');';
|
||||
run;
|
||||
data _null_;
|
||||
file &fref mod;
|
||||
put ');';
|
||||
run;
|
||||
|
||||
/* Create Unique Indexes, but only if they were not already defined within
|
||||
the Constraints section. */
|
||||
data _null_;
|
||||
*length ds $128;
|
||||
set &idxinfo(
|
||||
where=(
|
||||
memname="&curds"
|
||||
and unique='yes'
|
||||
and indxname not in (
|
||||
%sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
|
||||
/* Create Unique Indexes, but only if they were not already defined within
|
||||
the Constraints section. */
|
||||
data _null_;
|
||||
*length ds $128;
|
||||
set &idxinfo(
|
||||
where=(
|
||||
memname="&curds"
|
||||
and unique='yes'
|
||||
and indxname not in (
|
||||
%sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
file &fref mod;
|
||||
by idxusage indxname;
|
||||
/* ds=cats(libname,'.',memname); */
|
||||
if first.indxname then do;
|
||||
);
|
||||
file &fref mod;
|
||||
by idxusage indxname;
|
||||
if first.indxname then do;
|
||||
put 'CREATE UNIQUE INDEX "' indxname +(-1) '" ' "ON &schema..&curds(";
|
||||
put ' "' name +(-1) '"' ;
|
||||
end;
|
||||
else put ' ,"' name +(-1) '"';
|
||||
*else put ' ,' name ;
|
||||
if last.indxname then do;
|
||||
put ');';
|
||||
end;
|
||||
run;
|
||||
|
||||
end;
|
||||
else put ' ,"' name +(-1) '"';
|
||||
if last.indxname then do;
|
||||
put ');';
|
||||
end;
|
||||
run;
|
||||
%end;
|
||||
%end;
|
||||
%end;
|
||||
%if %upcase(&showlog)=YES %then %do;
|
||||
@@ -378,4 +397,4 @@ run;
|
||||
run;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_getddl;
|
||||
@@ -70,4 +70,4 @@ create table &outds (rename=(
|
||||
out=&outds(rename=(_name_=NAME COL1=MAXLEN));
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_getmaxvarlengths;
|
||||
@@ -301,4 +301,4 @@
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_guesspk;
|
||||
@@ -20,6 +20,7 @@
|
||||
@li mf_getvartype.sas
|
||||
|
||||
@param [in] libds dataset to hash
|
||||
@param [in] salt= Provide a salt (could be, for instance, the dataset name)
|
||||
@param [out] outds= (work.mf_hashdataset) The output dataset to create. This
|
||||
will contain one column (hashkey) with one observation (a hex32.
|
||||
representation of the input hash)
|
||||
@@ -33,7 +34,8 @@
|
||||
|
||||
%macro mp_hashdataset(
|
||||
libds,
|
||||
outds=
|
||||
outds=,
|
||||
salt=
|
||||
)/*/STORE SOURCE*/;
|
||||
%if %mf_getattrn(&libds,NLOBS)=0 %then %do;
|
||||
%put %str(WARN)ING: Dataset &libds is empty;, or is not a dataset;
|
||||
@@ -53,7 +55,7 @@
|
||||
%let varlist=%mf_getvarlist(&libds);
|
||||
data &outds(rename=(&keyvar=hashkey) keep=&keyvar);
|
||||
length &prevkeyvar &keyvar $32;
|
||||
retain &prevkeyvar;
|
||||
retain &prevkeyvar "%sysfunc(md5(%str(&salt)),$hex32.)";
|
||||
set &libds end=&lastvar;
|
||||
/* hash should include previous row */
|
||||
&keyvar=put(md5(&prevkeyvar
|
||||
@@ -72,4 +74,4 @@
|
||||
if &lastvar then output;
|
||||
run;
|
||||
%end;
|
||||
%mend;
|
||||
%mend mp_hashdataset;
|
||||
@@ -102,7 +102,8 @@
|
||||
%let fmtds=%scan(&syslast,2,.);
|
||||
/* prepare formats and varnames */
|
||||
data _null_;
|
||||
set &fmtds end=last;
|
||||
if _n_=1 then call symputx('nobs',nobs,'l');
|
||||
set &fmtds end=last nobs=nobs;
|
||||
name=upcase(name);
|
||||
/* fix formats */
|
||||
if type=2 or type=6 then do;
|
||||
@@ -128,7 +129,6 @@
|
||||
call symputx(cats('len',_n_),newlen,'l');
|
||||
call symputx(cats('fmt',_n_),fmt,'l');
|
||||
call symputx(cats('type',_n_),type,'l');
|
||||
if last then call symputx('nobs',_n_,'l');
|
||||
run;
|
||||
data &fmtds;
|
||||
/* rename on entry */
|
||||
@@ -147,7 +147,7 @@
|
||||
run;
|
||||
%let ds=&fmtds;
|
||||
%end; /* &fmt=Y */
|
||||
data _null_;file &jref mod ;
|
||||
data _null_;file &jref mod encoding='utf-8';
|
||||
put "["; call symputx('cols',0,'l');
|
||||
proc sort
|
||||
data=sashelp.vcolumn(where=(libname='WORK' & memname="%upcase(&ds)"))
|
||||
|
||||
@@ -75,4 +75,4 @@ select distinct lowcase(memname)
|
||||
)
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_lib2cards;
|
||||
73
base/mp_lib2inserts.sas
Normal file
73
base/mp_lib2inserts.sas
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
@file
|
||||
@brief Convert all data in a library to SQL insert statements
|
||||
@details Gets list of members then calls the <code>%mp_ds2inserts()</code>
|
||||
macro.
|
||||
Usage:
|
||||
|
||||
%mp_getddl(sashelp, schema=work, fref=tempref)
|
||||
|
||||
%mp_lib2inserts(sashelp, schema=work, outref=tempref)
|
||||
|
||||
%inc tempref;
|
||||
|
||||
|
||||
The output will be one file in the outref fileref.
|
||||
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_ds2inserts.sas
|
||||
|
||||
|
||||
@param [in] lib Library in which to convert all datasets to inserts
|
||||
@param [in] flavour= (SAS) The SQL flavour to be applied to the output. Valid
|
||||
options:
|
||||
@li SAS (default) - suitable for regular proc sql
|
||||
@li PGSQL - Used for Postgres databases
|
||||
@param [in] maxobs= (max) The max number of observations (per table) to create
|
||||
@param [out] outref= Output fileref in which to create the insert statements.
|
||||
If it exists, it will be appended to, otherwise it will be created.
|
||||
@param [out] schema= (0) The schema of the target database, or the libref.
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
**/
|
||||
|
||||
%macro mp_lib2inserts(lib
|
||||
,flavour=SAS
|
||||
,outref=0
|
||||
,schema=0
|
||||
,maxobs=max
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
/* Find the tables */
|
||||
%local x ds memlist;
|
||||
proc sql noprint;
|
||||
select distinct lowcase(memname)
|
||||
into: memlist
|
||||
separated by ' '
|
||||
from dictionary.tables
|
||||
where upcase(libname)="%upcase(&lib)"
|
||||
and memtype='DATA'; /* exclude views */
|
||||
|
||||
|
||||
%let flavour=%upcase(&flavour);
|
||||
%if &flavour ne SAS and &flavour ne PGSQL %then %do;
|
||||
%put %str(WAR)NING: &flavour is not supported;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
|
||||
/* create the inserts */
|
||||
%do x=1 %to %sysfunc(countw(&memlist));
|
||||
%let ds=%scan(&memlist,&x);
|
||||
%mp_ds2inserts(&lib..&ds
|
||||
,outref=&outref
|
||||
,schema=&schema
|
||||
,outds=&ds
|
||||
,flavour=&flavour
|
||||
,maxobs=&maxobs
|
||||
)
|
||||
%end;
|
||||
|
||||
%mend mp_lib2inserts;
|
||||
@@ -39,4 +39,4 @@
|
||||
,dttm=%sysfunc(datetime());
|
||||
quit;
|
||||
|
||||
%mend;
|
||||
%mend mp_perflog;
|
||||
@@ -85,4 +85,4 @@
|
||||
"with record &record and " _n_=;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_prevobs;
|
||||
@@ -87,4 +87,4 @@ insert into &outds select distinct * from &append_ds;
|
||||
)
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_recursivejoin;
|
||||
|
||||
@@ -30,4 +30,4 @@ data _null_;
|
||||
end;
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_resetoption;
|
||||
@@ -46,4 +46,4 @@
|
||||
|
||||
|
||||
|
||||
%mend;
|
||||
%mend mp_runddl;
|
||||
@@ -117,4 +117,4 @@ proc sql
|
||||
|
||||
%put process finished at %sysfunc(datetime(),datetime19.);
|
||||
|
||||
%mend;
|
||||
%mend mp_searchdata;
|
||||
|
||||
@@ -49,4 +49,4 @@
|
||||
|
||||
quit;
|
||||
|
||||
%mend;
|
||||
%mend mp_setkeyvalue;
|
||||
@@ -71,4 +71,4 @@
|
||||
proc append base=&libds data=&syslast nowarn;run;
|
||||
|
||||
options &etls_syntaxcheck;
|
||||
%mend;
|
||||
%mend mp_stprequests;
|
||||
@@ -134,4 +134,4 @@ run;
|
||||
%mp_binarycopy(inloc="&inloc",outref=_webout)
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mp_streamfile;
|
||||
|
||||
@@ -89,4 +89,4 @@ quit;
|
||||
libname &lib clear;
|
||||
|
||||
|
||||
%mend;
|
||||
%mend mp_testjob;
|
||||
@@ -22,8 +22,11 @@
|
||||
|mustbevalidname|can be anything, oops, %abort!!|
|
||||
|
||||
@param [in] debug= (log) Provide the _debug value
|
||||
@param [in] viyaresult=(WEBOUT_JSON) The Viya result type to return. For
|
||||
@param [in] mdebug= (0) Set to 1 to provide macro debugging
|
||||
@param [in] viyaresult= (WEBOUT_JSON) The Viya result type to return. For
|
||||
more info, see mv_getjobresult.sas
|
||||
@param [in] viyacontext= (SAS Job Execution compute context) The Viya compute
|
||||
context on which to run the service
|
||||
@param [out] outlib= (0) Output libref to contain the final tables. Set to
|
||||
0 if the service output is not in JSON format.
|
||||
@param [out] outref= (0) Output fileref to create, to contain the full _webout
|
||||
@@ -47,17 +50,18 @@
|
||||
inputfiles=0,
|
||||
inputparams=0,
|
||||
debug=log,
|
||||
mdebug=0,
|
||||
outlib=0,
|
||||
outref=0,
|
||||
viyaresult=WEBOUT_JSON
|
||||
viyaresult=WEBOUT_JSON,
|
||||
viyacontext=SAS Job Execution compute context
|
||||
)/*/STORE SOURCE*/;
|
||||
%local mdebug;
|
||||
%if &debug ne 0 %then %do;
|
||||
%let mdebug=1;
|
||||
%local dbg;
|
||||
%if &mdebug=1 %then %do;
|
||||
%put &sysmacroname entry vars:;
|
||||
%put _local_;
|
||||
%end;
|
||||
%else %let mdebug=0;
|
||||
%else %let dbg=*;
|
||||
|
||||
/* sanitise inputparams */
|
||||
%local pcnt;
|
||||
@@ -212,6 +216,7 @@
|
||||
|
||||
data &ds1;
|
||||
retain _program "&program";
|
||||
retain _contextname "&viyacontext";
|
||||
set &ds1;
|
||||
putlog "&sysmacroname inputparams:";
|
||||
putlog (_all_)(=);
|
||||
|
||||
@@ -56,4 +56,4 @@ data &outds;
|
||||
duration_seconds=end_dttm-start_dttm;
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_testwritespeedlibrary;
|
||||
@@ -68,4 +68,4 @@ data &outds ;
|
||||
rc=filename('tmp');
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_tree;
|
||||
@@ -63,4 +63,4 @@ data _null_;
|
||||
!!'filename &fname2 clear; filename &fname3 clear;');
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mp_unzip;
|
||||
@@ -90,4 +90,4 @@ alter table &libds modify &var char(&len);
|
||||
|
||||
%mp_createconstraints(inds=&dsconst,outds=&dsconst._addd,execute=YES)
|
||||
|
||||
%mend;
|
||||
%mend mp_updatevarlength;
|
||||
|
||||
@@ -76,4 +76,4 @@ ods package publish archive properties
|
||||
(archive_name="&outname..zip" archive_path="&outpath");
|
||||
ods package close;
|
||||
|
||||
%mend;
|
||||
%mend mp_zip;
|
||||
2
build.py
2
build.py
@@ -23,7 +23,7 @@ for file in files:
|
||||
ml.write(" put '" + line.rstrip().replace("'","''") + " ';\n")
|
||||
ml.write("run;\n\n")
|
||||
ml.write("%inc \"%sysfunc(pathname(work))/" + name + ".lua\";\n\n")
|
||||
ml.write("%mend;\n")
|
||||
ml.write("%mend " + name + ";\n")
|
||||
|
||||
ml.close()
|
||||
|
||||
|
||||
@@ -391,4 +391,4 @@ run;
|
||||
|
||||
%inc "%sysfunc(pathname(work))/ml_json.lua";
|
||||
|
||||
%mend;
|
||||
%mend ml_json;
|
||||
|
||||
7
main.dox
7
main.dox
@@ -42,6 +42,13 @@
|
||||
|
||||
*/
|
||||
|
||||
/*! \dir Tests
|
||||
* \brief SASjs Tests
|
||||
* \details These folders contain the macro tests. They are first compiled
|
||||
and deployed (sasjs cbd) then executed (sasjs test).
|
||||
|
||||
*/
|
||||
|
||||
/*! \dir viya
|
||||
* \brief Viya macros
|
||||
* \details These macros have the following attributes:
|
||||
|
||||
@@ -95,4 +95,4 @@ run;
|
||||
|
||||
filename __us2grp clear;
|
||||
|
||||
%mend;
|
||||
%mend mm_adduser2group;
|
||||
@@ -460,4 +460,4 @@ run;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mm_assigndirectlib;
|
||||
|
||||
@@ -75,4 +75,4 @@
|
||||
%else %do;
|
||||
%put NOTE: Library &libref is already assigned;
|
||||
%end;
|
||||
%mend;
|
||||
%mend mm_assignlib;
|
||||
|
||||
@@ -152,4 +152,4 @@ run;
|
||||
%else %put NOTE: Application (&name) successfully created in (&tree)!;
|
||||
|
||||
|
||||
%mend;
|
||||
%mend mm_createapplication;
|
||||
@@ -80,4 +80,4 @@ data _null_;
|
||||
if last then call execute('call missing(of _all_);stop;run;');
|
||||
run;
|
||||
|
||||
%mend;
|
||||
%mend mm_createdataset;
|
||||
@@ -122,4 +122,4 @@ run;
|
||||
run;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mm_createdocument;
|
||||
@@ -157,4 +157,4 @@ run;
|
||||
%end;
|
||||
|
||||
%put &sysmacroname: execution finished for &path;
|
||||
%mend;
|
||||
%mend mm_createfolder;
|
||||
@@ -318,4 +318,4 @@ filename &frefout temp;
|
||||
filename &frefout clear;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mm_createlibrary;
|
||||
|
||||
@@ -385,4 +385,4 @@ run;
|
||||
%put %str(WARN)ING: STPTYPE=*&stptype* not recognised!;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mm_createstp;
|
||||
@@ -22,7 +22,7 @@ Usage:
|
||||
%webout(OBJ,example2) * Object format, easier to work with ;
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mm_createwebservice(path=/Public/app/common,name=appInit)
|
||||
%mm_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001)
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mm_createstp.sas
|
||||
@@ -37,12 +37,15 @@ Usage:
|
||||
@param desc= The description of the service (optional)
|
||||
@param precode= Space separated list of filerefs, pointing to the code that
|
||||
needs to be attached to the beginning of the service (optional)
|
||||
@param code= Space seperated fileref(s) of the actual code to be added
|
||||
@param server= The server which will run the STP. Server name or uri is fine.
|
||||
@param mDebug= set to 1 to show debug messages in the log
|
||||
@param replace= select YES to replace any existing service in that location
|
||||
@param adapter= the macro uses the sasjs adapter by default. To use another
|
||||
adapter, add a (different) fileref here.
|
||||
@param code=(ft15f001) Space seperated fileref(s) of the actual code to be
|
||||
added
|
||||
@param server=(SASApp) The server which will run the STP. Server name or uri
|
||||
is fine.
|
||||
@param mDebug=(0) set to 1 to show debug messages in the log
|
||||
@param replace=(YES) select NO to avoid replacing an existing service in that
|
||||
location
|
||||
@param adapter=(sasjs) the macro uses the sasjs adapter by default. To use
|
||||
another adapter, add a (different) fileref here.
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
@@ -52,11 +55,11 @@ Usage:
|
||||
%macro mm_createwebservice(path=
|
||||
,name=initService
|
||||
,precode=
|
||||
,code=
|
||||
,code=ft15f001
|
||||
,desc=This stp was created automagically by the mm_createwebservice macro
|
||||
,mDebug=0
|
||||
,server=SASApp
|
||||
,replace=NO
|
||||
,replace=YES
|
||||
,adapter=sasjs
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
@@ -131,7 +134,8 @@ data _null_;
|
||||
put ' %let fmtds=%scan(&syslast,2,.); ';
|
||||
put ' /* prepare formats and varnames */ ';
|
||||
put ' data _null_; ';
|
||||
put ' set &fmtds end=last; ';
|
||||
put ' if _n_=1 then call symputx(''nobs'',nobs,''l''); ';
|
||||
put ' set &fmtds end=last nobs=nobs; ';
|
||||
put ' name=upcase(name); ';
|
||||
put ' /* fix formats */ ';
|
||||
put ' if type=2 or type=6 then do; ';
|
||||
@@ -157,7 +161,6 @@ data _null_;
|
||||
put ' call symputx(cats(''len'',_n_),newlen,''l''); ';
|
||||
put ' call symputx(cats(''fmt'',_n_),fmt,''l''); ';
|
||||
put ' call symputx(cats(''type'',_n_),type,''l''); ';
|
||||
put ' if last then call symputx(''nobs'',_n_,''l''); ';
|
||||
put ' run; ';
|
||||
put ' data &fmtds; ';
|
||||
put ' /* rename on entry */ ';
|
||||
@@ -176,7 +179,7 @@ data _null_;
|
||||
put ' run; ';
|
||||
put ' %let ds=&fmtds; ';
|
||||
put ' %end; /* &fmt=Y */ ';
|
||||
put ' data _null_;file &jref mod ; ';
|
||||
put ' data _null_;file &jref mod encoding=''utf-8''; ';
|
||||
put ' put "["; call symputx(''cols'',0,''l''); ';
|
||||
put ' proc sort ';
|
||||
put ' data=sashelp.vcolumn(where=(libname=''WORK'' & memname="%upcase(&ds)")) ';
|
||||
@@ -263,7 +266,12 @@ data _null_;
|
||||
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y); ';
|
||||
put '%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug ';
|
||||
put ' sasjs_tables; ';
|
||||
put '%local i tempds; ';
|
||||
put '%local i tempds jsonengine; ';
|
||||
put ' ';
|
||||
put '/* see https://github.com/sasjs/core/issues/41 */ ';
|
||||
put '%if "%upcase(&SYSENCODING)" ne "UTF-8" %then %let jsonengine=PROCJSON; ';
|
||||
put '%else %let jsonengine=DATASTEP; ';
|
||||
put ' ';
|
||||
put ' ';
|
||||
put '%if &action=FETCH %then %do; ';
|
||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
||||
@@ -298,7 +306,7 @@ data _null_;
|
||||
put ' OPTIONS NOBOMFILE; ';
|
||||
put ' ';
|
||||
put ' /** ';
|
||||
put ' * check engine type to avoid the below err message: ';
|
||||
put ' * check xengine type to avoid the below err message: ';
|
||||
put ' * > Function is only valid for filerefs using the CACHE access method. ';
|
||||
put ' */ ';
|
||||
put ' data _null_; ';
|
||||
@@ -319,8 +327,8 @@ data _null_;
|
||||
put '%end; ';
|
||||
put ' ';
|
||||
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt ';
|
||||
put ' ,engine=DATASTEP,dbg=%str(&_debug) ';
|
||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
||||
put ' ,engine=&jsonengine,dbg=%str(&_debug) ';
|
||||
put ' ) ';
|
||||
put '%end; ';
|
||||
put '%else %if &action=CLOSE %then %do; ';
|
||||
@@ -333,7 +341,7 @@ data _null_;
|
||||
put ' %local wtcnt;%let wtcnt=0; ';
|
||||
put ' data _null_; ';
|
||||
put ' set &tempds; ';
|
||||
put ' if not (name =:"DATA"); ';
|
||||
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
||||
put ' i+1; ';
|
||||
put ' call symputx(''wt''!!left(i),name,''l''); ';
|
||||
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||
@@ -353,8 +361,8 @@ data _null_;
|
||||
put ' put " ""&wt"" : {"; ';
|
||||
put ' put ''"nlobs":'' nlobs; ';
|
||||
put ' put '',"nvars":'' nvars; ';
|
||||
put ' %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) ';
|
||||
put ' %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=&jsonengine) ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=&jsonengine) ';
|
||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
||||
put ' put "}"; ';
|
||||
put ' %end; ';
|
||||
@@ -378,6 +386,8 @@ data _null_;
|
||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||
put ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; ';
|
||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),datetime20.3)" ''" ''; ';
|
||||
put ' put "}" @; ';
|
||||
@@ -387,7 +397,7 @@ data _null_;
|
||||
put ' run; ';
|
||||
put '%end; ';
|
||||
put ' ';
|
||||
put '%mend; ';
|
||||
put '%mend mm_webout; ';
|
||||
put ' ';
|
||||
put '%macro mf_getuser(type=META ';
|
||||
put ')/*/STORE SOURCE*/; ';
|
||||
@@ -405,7 +415,7 @@ data _null_;
|
||||
put ' ';
|
||||
put ' %quote(&user) ';
|
||||
put ' ';
|
||||
put '%mend; ';
|
||||
put '%mend mf_getuser; ';
|
||||
/* WEBOUT END */
|
||||
put '%macro webout(action,ds,dslabel=,fmt=);';
|
||||
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt)';
|
||||
@@ -466,4 +476,4 @@ run;
|
||||
%put &url?_PROGRAM=&path/&name;
|
||||
%put ;%put ;%put ;%put ;%put ;%put ;
|
||||
|
||||
%mend;
|
||||
%mend mm_createwebservice;
|
||||
|
||||
@@ -68,4 +68,4 @@ run;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
%mend mm_deletedocument;
|
||||
|
||||
@@ -89,4 +89,4 @@ run;
|
||||
|
||||
%put &sysmacroname: Library &name (&liburi) was successfully deleted;
|
||||
|
||||
%mend;
|
||||
%mend mm_deletelibrary;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user