53 Commits

Author SHA1 Message Date
519d8953b5 chore(release): 7.0.1 [skip ci]
## [7.0.1](https://git.datacontroller.io/dc/dc/compare/v7.0.0...v7.0.1) (2025-06-11)

### Bug Fixes

* refresh process ([4ecd186](4ecd186e5c))
2025-06-11 18:47:43 +00:00
14a616fc1b Merge pull request 'fix: refresh process' (#173) from issue157 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m9s
Release / Build-and-test-development (push) Successful in 8m45s
Release / release (push) Successful in 8m47s
Reviewed-on: #173
2025-06-11 18:05:06 +00:00
bfe5a8626f Merge branch 'main' into issue157
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m18s
Build / Build-and-test-development (pull_request) Successful in 8m43s
2025-06-11 18:04:48 +00:00
4ecd186e5c fix: refresh process
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m15s
Build / Build-and-test-development (pull_request) Successful in 8m44s
2025-06-11 19:04:21 +01:00
8c60473c15 chore(release): 7.0.0 [skip ci]
# [7.0.0](https://git.datacontroller.io/dc/dc/compare/v6.16.2...v7.0.0) (2025-06-11)

### Bug Fixes

* bumping adapter to re-enable JES API method ([e874143](e874143a95))
* commit git hooks checking lint ([69f687a](69f687a85f))
* ensuring apploc is not case sensitive. Closes [#171](#171) ([24545f2](24545f2acd))
* export unregistered formats ([f6d7d6f](f6d7d6f90c)), closes [#158](#158)
* reload startupservice after user approves the MPE_TABLES page ([e5f8e50](e5f8e500c1))
* showing catalog_cnt in libinfo ([e44a25d](e44a25dcc3)), closes [#160](#160)

### Features

* adding 4 new tables for catalogs ([e4dbab8](e4dbab8b16))
* capturing catalog specific information, closes [#159](#159) ([b4c586a](b4c586a859))
* viewer added catalog_cnt ([2aa19d1](2aa19d1dca))

### BREAKING CHANGES

* Introduction of 4 new tables for capturing information related to catalogs and their objects.  Migration script prepared and available in the DB folder (usual place)
2025-06-11 13:46:10 +00:00
bb126eba5b Merge pull request 'Reload startupservice after user approves the MPE_TABLES changes' (#170) from issue157 into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m8s
Release / Build-and-test-development (push) Successful in 8m47s
Release / release (push) Successful in 8m50s
Reviewed-on: #170
2025-06-11 13:16:22 +00:00
d1998422d2 chore: fix for mpe_datastatus_libs
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m19s
Build / Build-and-test-development (pull_request) Successful in 8m45s
2025-06-11 14:15:50 +01:00
69f687a85f fix: commit git hooks checking lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m11s
Build / Build-and-test-development (pull_request) Successful in 8m34s
2025-06-11 13:11:30 +02:00
2aa19d1dca feat: viewer added catalog_cnt
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 48s
Build / Build-and-test-development (pull_request) Successful in 8m49s
2025-06-11 12:57:10 +02:00
e44a25dcc3 fix: showing catalog_cnt in libinfo
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m19s
Build / Build-and-test-development (pull_request) Successful in 8m53s
Closes #160
2025-06-11 10:06:52 +01:00
efb5ffa906 chore: reverting accidental change
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m4s
Build / Build-and-test-development (pull_request) Successful in 8m33s
2025-06-10 22:45:39 +01:00
b4c586a859 feat: capturing catalog specific information, closes #159
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m12s
Build / Build-and-test-development (pull_request) Successful in 8m35s
BREAKING CHANGE:  Introduction of 4 new tables for capturing information related to catalogs and their objects.  Migration script prepared and available in the DB folder (usual place)
2025-06-10 22:40:09 +01:00
e874143a95 fix: bumping adapter to re-enable JES API method 2025-06-10 16:18:56 +01:00
e4dbab8b16 feat: adding 4 new tables for catalogs 2025-06-10 16:18:30 +01:00
f6d7d6f90c fix: export unregistered formats
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m14s
Build / Build-and-test-development (pull_request) Successful in 9m0s
Closes #158
2025-06-10 09:41:18 +01:00
063c90caf4 chore(docs): readme fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m3s
Build / Build-and-test-development (pull_request) Successful in 8m38s
2025-06-06 23:24:35 +01:00
2011c2eee7 chore(docs): updating README with viya deploy details
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m0s
Build / Build-and-test-development (pull_request) Successful in 8m28s
2025-06-06 23:23:47 +01:00
24545f2acd fix: ensuring apploc is not case sensitive. Closes #171
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m6s
Build / Build-and-test-development (pull_request) Successful in 8m38s
2025-06-06 21:05:08 +01:00
a7c81245ff Merge branch 'main' into issue157
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m6s
Build / Build-and-test-development (pull_request) Successful in 8m45s
2025-06-06 13:17:17 +00:00
4f2c993b2d style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m3s
Build / Build-and-test-development (pull_request) Successful in 8m35s
2025-06-06 15:03:51 +02:00
e5f8e500c1 fix: reload startupservice after user approves the MPE_TABLES page 2025-06-06 15:03:36 +02:00
a61e2de140 chore(release): 6.16.2 [skip ci]
## [6.16.2](https://git.datacontroller.io/dc/dc/compare/v6.16.1...v6.16.2) (2025-06-06)

### Bug Fixes

* streaming viya deploy `isStreaming` function stability fix ([4830c6d](4830c6d219))
2025-06-06 11:36:00 +00:00
881d2b060e Merge pull request 'fix: streaming viya deploy isStreaming function stability fix' (#169) from viya-deploy into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 3m53s
Release / Build-and-test-development (push) Successful in 8m36s
Release / release (push) Successful in 8m18s
Reviewed-on: #169
2025-06-06 11:08:03 +00:00
4830c6d219 fix: streaming viya deploy isStreaming function stability fix
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 3m59s
Build / Build-and-test-development (pull_request) Successful in 8m30s
2025-06-06 13:06:55 +02:00
4c3c9ac88c chore(release): 6.16.1 [skip ci]
## [6.16.1](https://git.datacontroller.io/dc/dc/compare/v6.16.0...v6.16.1) (2025-06-06)

### Bug Fixes

* viya deploy updating index html based on URL ([86134f4](86134f478a))
* viya streamed app deploy page flow fix ([89ab296](89ab296151))
2025-06-06 10:35:30 +00:00
7e1c610a4d Merge pull request 'Viya deploy, updating the compute context in index.html file, found based on URL' (#168) from viya-deploy into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 3m54s
Release / Build-and-test-development (push) Successful in 8m30s
Release / release (push) Successful in 8m19s
Reviewed-on: #168
2025-06-06 10:19:20 +00:00
8139f495ce style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m4s
Build / Build-and-test-development (pull_request) Successful in 8m33s
2025-06-06 12:06:10 +02:00
89ab296151 fix: viya streamed app deploy page flow fix 2025-06-06 12:05:52 +02:00
a0dc92c403 style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m15s
Build / Build-and-test-development (pull_request) Successful in 8m34s
2025-06-06 10:58:01 +02:00
86134f478a fix: viya deploy updating index html based on URL 2025-06-06 10:57:41 +02:00
9a2addc18e chore(release): 6.16.0 [skip ci]
# [6.16.0](https://git.datacontroller.io/dc/dc/compare/v6.15.2...v6.16.0) (2025-06-05)

### Bug Fixes

* adapter bump ([ca7caa2](ca7caa25b6))
* automatic viya deploy timing issue ([037a97b](037a97b6ff))
* bump core to ensure ff works on viya streaming deploy ([cbd69df](cbd69df708)), closes [#156](#156)
* viya deploy load data timing ([abdbb67](abdbb67471))

### Features

* viya deploy, update the index.html contextname ([7223955](72239558af))
2025-06-05 13:53:03 +00:00
9264ce2a60 Merge pull request 'Adapter bump, including getFileContent and updateFileContent' (#167) from adapter-bump into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m4s
Release / Build-and-test-development (push) Successful in 9m9s
Release / release (push) Successful in 8m19s
Reviewed-on: #167
2025-06-05 13:17:06 +00:00
cbd69df708 fix: bump core to ensure ff works on viya streaming deploy
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m3s
Build / Build-and-test-development (pull_request) Successful in 8m39s
closes #156 (along with previous releases)
2025-06-05 14:16:44 +01:00
ca7caa25b6 fix: adapter bump
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m9s
Build / Build-and-test-development (pull_request) Successful in 8m45s
2025-06-05 14:49:21 +02:00
c10330627f Merge pull request 'Viya smooth deploy' (#166) from deploy-context into main
Some checks failed
Release / Build-production-and-ng-test (push) Has been cancelled
Release / Build-and-test-development (push) Has been cancelled
Release / release (push) Has been cancelled
Reviewed-on: #166
2025-06-05 12:30:29 +00:00
d80c59afce Merge branch 'main' into deploy-context
Some checks failed
Build / Build-and-ng-test (pull_request) Has been cancelled
Build / Build-and-test-development (pull_request) Has been cancelled
2025-06-05 12:30:19 +00:00
abdbb67471 fix: viya deploy load data timing
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 4m0s
Build / Build-and-test-development (pull_request) Failing after 2h56m12s
2025-06-05 12:07:26 +02:00
037a97b6ff fix: automatic viya deploy timing issue 2025-06-04 17:37:44 +02:00
a0a529ad38 style: lint 2025-06-04 17:36:13 +02:00
72239558af feat: viya deploy, update the index.html contextname 2025-06-04 17:35:15 +02:00
d2097ad6dd chore(release): 6.15.2 [skip ci]
## [6.15.2](https://git.datacontroller.io/dc/dc/compare/v6.15.1...v6.15.2) (2025-06-04)

### Bug Fixes

* pipeline updates for DC.html ([624a7a8](624a7a8f37))
2025-06-04 14:26:44 +00:00
1bd542cddb Merge pull request 'fix: pipeline updates for DC.html' (#165) from issue156b into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m29s
Release / Build-and-test-development (push) Successful in 8m37s
Release / release (push) Successful in 8m17s
Reviewed-on: #165
2025-06-04 13:53:24 +00:00
fb1c1ee874 Merge branch 'main' into issue156b
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m1s
Build / Build-and-test-development (pull_request) Successful in 8m34s
2025-06-04 13:48:58 +00:00
624a7a8f37 fix: pipeline updates for DC.html
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m5s
Build / Build-and-test-development (pull_request) Successful in 8m42s
2025-06-04 14:41:36 +01:00
381378f532 chore(release): 6.15.1 [skip ci]
## [6.15.1](https://git.datacontroller.io/dc/dc/compare/v6.15.0...v6.15.1) (2025-06-04)

### Bug Fixes

* updating pipeline to default to streaming on viya ([4b55894](4b558948d9))
2025-06-04 12:57:08 +00:00
af05486c0e Merge pull request 'fix: updating pipeline to default to streaming on viya' (#164) from issue156b into main
Some checks failed
Release / Build-production-and-ng-test (push) Successful in 3m57s
Release / Build-and-test-development (push) Successful in 8m41s
Release / release (push) Failing after 7m35s
Reviewed-on: #164
2025-06-04 12:28:12 +00:00
4b558948d9 fix: updating pipeline to default to streaming on viya
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 4m4s
Build / Build-and-test-development (pull_request) Successful in 8m33s
Also added error captures on makedata
2025-06-04 13:27:28 +01:00
d9cff42f5c chore(release): 6.15.0 [skip ci]
# [6.15.0](https://git.datacontroller.io/dc/dc/compare/v6.14.10...v6.15.0) (2025-06-04)

### Bug Fixes

* makedata with context name ([da4d0b2](da4d0b28c7))

### Features

* viya deploy context ([6c96ef7](6c96ef7fb0))
2025-06-04 09:26:02 +00:00
2a3d2b8d0d Merge pull request 'feat: viya deploy context' (#163) from deploy-context into main
All checks were successful
Release / Build-production-and-ng-test (push) Successful in 4m3s
Release / Build-and-test-development (push) Successful in 8m39s
Release / release (push) Successful in 8m30s
Reviewed-on: #163
2025-06-04 09:09:28 +00:00
d0f453d291 chore: typo
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 3m59s
Build / Build-and-test-development (pull_request) Successful in 8m31s
2025-06-04 09:41:06 +02:00
8e65dd0eae style: lint
All checks were successful
Build / Build-and-ng-test (pull_request) Successful in 3m59s
Build / Build-and-test-development (pull_request) Successful in 8m25s
2025-06-03 21:06:48 +02:00
da4d0b28c7 fix: makedata with context name
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 49s
Build / Build-and-test-development (pull_request) Successful in 8m32s
2025-06-03 21:00:54 +02:00
6c96ef7fb0 feat: viya deploy context
Some checks failed
Build / Build-and-ng-test (pull_request) Failing after 47s
Build / Build-and-test-development (pull_request) Successful in 8m35s
2025-06-03 20:22:39 +02:00
52 changed files with 1351 additions and 276 deletions

View File

@ -1,11 +1,12 @@
#!/bin/sh #!/bin/sh
# Avoid commits to the master branch # Using `--silent` helps for showing any errs in the first line of the response
BRANCH=`git rev-parse --abbrev-ref HEAD` # The first line is picked up by the VS Code GIT UI popup when rc is not 0
REGEX="^(master|development)$"
if [[ "$BRANCH" =~ $REGEX ]]; then if npm run --silent lint:silent ; then
echo "You are on branch $BRANCH. Are you sure you want to commit to this branch?" exit 0
echo "If so, commit with -n to bypass the pre-commit hook." else
exit 1 npm run --silent lint:fix
echo "❌ Prettier check failed! We ran lint:fix for you. Please add & commit again."
exit 1
fi fi

View File

@ -237,20 +237,20 @@ jobs:
cd sas cd sas
sasjs c -t viya sasjs c -t viya
rm -rf sasjsbuild/tests rm -rf sasjsbuild/tests
sed -i -e 's/servertype="SASJS"/servertype="SASVIYA"/g' sasjsbuild/services/clickme.html sed -i -e 's/servertype="SASJS"/servertype="SASVIYA"/g' sasjsbuild/services/DC.html
sasjs b -t viya
cp sasjsbuild/viya.sas ./demostream_viya.sas
# compile Viya Full deploy (without web)
rm -rf sasjsbuild/services/web
rm sasjsbuild/services/clickme.html
sasjs b -t viya sasjs b -t viya
cp sasjsbuild/viya.sas ./viya.sas cp sasjsbuild/viya.sas ./viya.sas
cp sasjsbuild/viya.json ./viya.json # compile Viya Full deploy (without web)
rm -rf sasjsbuild/services/web
rm sasjsbuild/services/DC.html
sasjs b -t viya
cp sasjsbuild/viya.sas ./viya_noweb.sas
cp sasjsbuild/viya.json ./viya_noweb.json
- name: Zip Frontend (including viya.json for full viya deploy) - name: Zip Frontend (including viya.json for full viya deploy)
run: | run: |
cd sas cd sas
cp sasjsbuild/viya.json ../client/dist cp sasjsbuild/viya.json ../client/dist/viya.json
cd .. cd ..
zip -r frontend.zip ./client/dist zip -r frontend.zip ./client/dist
@ -277,8 +277,8 @@ jobs:
URL="https://git.datacontroller.io/api/v1/repos/dc/dc/releases/$RELEASE_ID/assets?access_token=${{ secrets.RELEASE_TOKEN }}" URL="https://git.datacontroller.io/api/v1/repos/dc/dc/releases/$RELEASE_ID/assets?access_token=${{ secrets.RELEASE_TOKEN }}"
curl -k $URL -F attachment=@frontend.zip curl -k $URL -F attachment=@frontend.zip
curl -k $URL -F attachment=@sas/demostream_sas9.sas curl -k $URL -F attachment=@sas/demostream_sas9.sas
curl -k $URL -F attachment=@sas/demostream_viya.sas curl -k $URL -F attachment=@sas/viya.sas
curl -k $URL -F attachment=@sas/sasjs_server.json.zip curl -k $URL -F attachment=@sas/sasjs_server.json.zip
curl -k $URL -F attachment=@sas/sas9.sas curl -k $URL -F attachment=@sas/sas9.sas
curl -k $URL -F attachment=@sas/viya.sas curl -k $URL -F attachment=@sas/viya_noweb.sas
curl -k $URL -F attachment=@sas/viya.json curl -k $URL -F attachment=@sas/viya_noweb.json

View File

@ -1,3 +1,90 @@
## [7.0.1](https://git.datacontroller.io/dc/dc/compare/v7.0.0...v7.0.1) (2025-06-11)
### Bug Fixes
* refresh process ([4ecd186](https://git.datacontroller.io/dc/dc/commit/4ecd186e5cb22dd436f2d7f1200956f4e3f27425))
# [7.0.0](https://git.datacontroller.io/dc/dc/compare/v6.16.2...v7.0.0) (2025-06-11)
### Bug Fixes
* bumping adapter to re-enable JES API method ([e874143](https://git.datacontroller.io/dc/dc/commit/e874143a95d0ac2e56c0793e04b979c27f96d74b))
* commit git hooks checking lint ([69f687a](https://git.datacontroller.io/dc/dc/commit/69f687a85f1cc562346b6167813d617cb9bd3404))
* ensuring apploc is not case sensitive. Closes [#171](https://git.datacontroller.io/dc/dc/issues/171) ([24545f2](https://git.datacontroller.io/dc/dc/commit/24545f2acdd5bd73cbe062526f2bd043269cc6a3))
* export unregistered formats ([f6d7d6f](https://git.datacontroller.io/dc/dc/commit/f6d7d6f90c978ac8c071471dfb67a60834424de5)), closes [#158](https://git.datacontroller.io/dc/dc/issues/158)
* reload startupservice after user approves the MPE_TABLES page ([e5f8e50](https://git.datacontroller.io/dc/dc/commit/e5f8e500c125ee233c6f7af5ad0077c0ed6abfcb))
* showing catalog_cnt in libinfo ([e44a25d](https://git.datacontroller.io/dc/dc/commit/e44a25dcc39ba4b9714257c60da84c2dfa613a85)), closes [#160](https://git.datacontroller.io/dc/dc/issues/160)
### Features
* adding 4 new tables for catalogs ([e4dbab8](https://git.datacontroller.io/dc/dc/commit/e4dbab8b1654b24e610e4b0603d1cf2b02a451e2))
* capturing catalog specific information, closes [#159](https://git.datacontroller.io/dc/dc/issues/159) ([b4c586a](https://git.datacontroller.io/dc/dc/commit/b4c586a859929e0122cd46449e43d4ca597b8b2b))
* viewer added catalog_cnt ([2aa19d1](https://git.datacontroller.io/dc/dc/commit/2aa19d1dca747f41274a032cde78d8ba73d66224))
### BREAKING CHANGES
* Introduction of 4 new tables for capturing information related to catalogs and their objects. Migration script prepared and available in the DB folder (usual place)
## [6.16.2](https://git.datacontroller.io/dc/dc/compare/v6.16.1...v6.16.2) (2025-06-06)
### Bug Fixes
* streaming viya deploy `isStreaming` function stability fix ([4830c6d](https://git.datacontroller.io/dc/dc/commit/4830c6d2191cb47abcc7919bc1d49e55595e6121))
## [6.16.1](https://git.datacontroller.io/dc/dc/compare/v6.16.0...v6.16.1) (2025-06-06)
### Bug Fixes
* viya deploy updating index html based on URL ([86134f4](https://git.datacontroller.io/dc/dc/commit/86134f478ae0b9426e01bfcc9ca4ee597ca733f7))
* viya streamed app deploy page flow fix ([89ab296](https://git.datacontroller.io/dc/dc/commit/89ab2961513b245eeea48d1867c6496d3261761e))
# [6.16.0](https://git.datacontroller.io/dc/dc/compare/v6.15.2...v6.16.0) (2025-06-05)
### Bug Fixes
* adapter bump ([ca7caa2](https://git.datacontroller.io/dc/dc/commit/ca7caa25b6eea1bd4579fb8b67ec9b211a893079))
* automatic viya deploy timing issue ([037a97b](https://git.datacontroller.io/dc/dc/commit/037a97b6ffa27b40891531ae6812ebe5b5e71e34))
* bump core to ensure ff works on viya streaming deploy ([cbd69df](https://git.datacontroller.io/dc/dc/commit/cbd69df708edf3a8446115ca7315fac3557dcf97)), closes [#156](https://git.datacontroller.io/dc/dc/issues/156)
* viya deploy load data timing ([abdbb67](https://git.datacontroller.io/dc/dc/commit/abdbb674713796e5308eb4272197a5c253868a85))
### Features
* viya deploy, update the index.html contextname ([7223955](https://git.datacontroller.io/dc/dc/commit/72239558af2ee50cdfc71b7e185e6661ab568ba1))
## [6.15.2](https://git.datacontroller.io/dc/dc/compare/v6.15.1...v6.15.2) (2025-06-04)
### Bug Fixes
* pipeline updates for DC.html ([624a7a8](https://git.datacontroller.io/dc/dc/commit/624a7a8f37f0265cf576da310ac330c75aa417cf))
## [6.15.1](https://git.datacontroller.io/dc/dc/compare/v6.15.0...v6.15.1) (2025-06-04)
### Bug Fixes
* updating pipeline to default to streaming on viya ([4b55894](https://git.datacontroller.io/dc/dc/commit/4b558948d997f456ff25a12a58827fe0d2075493))
# [6.15.0](https://git.datacontroller.io/dc/dc/compare/v6.14.10...v6.15.0) (2025-06-04)
### Bug Fixes
* makedata with context name ([da4d0b2](https://git.datacontroller.io/dc/dc/commit/da4d0b28c7109afd6f96455e1e0e80a40d25a942))
### Features
* viya deploy context ([6c96ef7](https://git.datacontroller.io/dc/dc/commit/6c96ef7fb0a55754a84ff0a8bbab838b78c1acaf))
## [6.14.10](https://git.datacontroller.io/dc/dc/compare/v6.14.9...v6.14.10) (2025-06-02) ## [6.14.10](https://git.datacontroller.io/dc/dc/compare/v6.14.9...v6.14.10) (2025-06-02)

View File

@ -23,7 +23,16 @@ _Problems with the above include:_
Data Controller for SAS® solves all these issues in a simple-to-install, user-friendly, secure, documented, battle-tested web application. Available on Viya, SAS 9 EBI, and [SASjs Server](https://server.sasjs.io). Data Controller for SAS® solves all these issues in a simple-to-install, user-friendly, secure, documented, battle-tested web application. Available on Viya, SAS 9 EBI, and [SASjs Server](https://server.sasjs.io).
For more information: An individual Viya deploy can be done in just 2 lines of #SAS code!
```sas
filename dc url "https://git.datacontroller.io/dc/dc/releases/download/latest/viya.sas";
%inc dc;
```
For a multi-user deploy, using a shared system account, please see [deploy docs](https://docs.datacontroller.io/deploy-viya/).
For further information:
* Main site: https://datacontroller.io * Main site: https://datacontroller.io
* Docs: https://docs.datacontroller.io * Docs: https://docs.datacontroller.io

View File

@ -21,7 +21,7 @@
"@clr/icons": "^13.0.2", "@clr/icons": "^13.0.2",
"@clr/ui": "file:libraries/clr-ui-17.9.0.tgz", "@clr/ui": "file:libraries/clr-ui-17.9.0.tgz",
"@handsontable/angular": "^15.3.0", "@handsontable/angular": "^15.3.0",
"@sasjs/adapter": "^4.11.0", "@sasjs/adapter": "^4.12.1",
"@sasjs/utils": "^3.4.0", "@sasjs/utils": "^3.4.0",
"@sheet/crypto": "file:libraries/sheet-crypto.tgz", "@sheet/crypto": "file:libraries/sheet-crypto.tgz",
"@types/d3-graphviz": "^2.6.7", "@types/d3-graphviz": "^2.6.7",
@ -5912,9 +5912,9 @@
] ]
}, },
"node_modules/@sasjs/adapter": { "node_modules/@sasjs/adapter": {
"version": "4.11.3", "version": "4.12.1",
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-4.11.3.tgz", "resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-4.12.1.tgz",
"integrity": "sha512-KF6G4vzs4l4efjpCD02og3kB44uFfJ1u2UWu749VdHtLKNN9l+PO26/moR+YAmRmmz2I9sC3X09fZE1nlN6zgw==", "integrity": "sha512-0217oZIkrecOyQygRe6Azgc1C4TIcjB5noi15fU4Rd5GsfDpleKVfQQdzYZ7im/vesWlLIVl/yUT67MMaQe0ew==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {

View File

@ -49,7 +49,7 @@
"@clr/icons": "^13.0.2", "@clr/icons": "^13.0.2",
"@clr/ui": "file:libraries/clr-ui-17.9.0.tgz", "@clr/ui": "file:libraries/clr-ui-17.9.0.tgz",
"@handsontable/angular": "^15.3.0", "@handsontable/angular": "^15.3.0",
"@sasjs/adapter": "^4.11.0", "@sasjs/adapter": "^4.12.1",
"@sasjs/utils": "^3.4.0", "@sasjs/utils": "^3.4.0",
"@sheet/crypto": "file:libraries/sheet-crypto.tgz", "@sheet/crypto": "file:libraries/sheet-crypto.tgz",
"@types/d3-graphviz": "^2.6.7", "@types/d3-graphviz": "^2.6.7",

View File

@ -98,14 +98,14 @@
<label for="dcloc" class="mt-20 clr-control-label">DC Loc</label> <label for="dcloc" class="mt-20 clr-control-label">DC Loc</label>
<div class="mb-10 clr-control-container dc-loc-input-wrapper"> <div class="mb-10 clr-control-container dc-loc-input-wrapper">
<div class="clr-input-wrapper"> <div class="clr-input-wrapper small-mt">
<input clrInput name="dcloc" [(ngModel)]="dcPath" /> <input clrInput name="dcloc" [(ngModel)]="dcPath" />
</div> </div>
</div> </div>
<label for="dcloc" class="mt-20 clr-control-label">SAS Admin group</label> <label for="dcloc" class="mt-20 clr-control-label">SAS Admin group</label>
<div class="mb-10 clr-control-container"> <div class="mb-10 clr-control-container">
<div class="clr-input-wrapper"> <div class="clr-input-wrapper small-mt">
<select <select
*ngIf="!adminGroupsLoading" *ngIf="!adminGroupsLoading"
clrSelect clrSelect
@ -124,6 +124,42 @@
</div> </div>
</div> </div>
<label for="computeContext" class="mt-20 clr-control-label"
>Compute Context</label
>
<div class="mb-10 clr-control-container">
<div class="clr-input-wrapper small-mt">
<select
*ngIf="!computeContextsLoading"
clrSelect
name="options"
(ngModelChange)="onComputeContextChange($event)"
[(ngModel)]="selectedComputeContext"
>
<option
*ngFor="let computeContext of computeContexts"
[value]="computeContext.id"
>
{{ computeContext.name }}
</option>
</select>
<clr-spinner
clrInline
class="spinner-sm"
*ngIf="computeContextsLoading"
></clr-spinner>
</div>
</div>
<ng-container *ngIf="runningAsUser">
<label for="dcloc" class="mt-20 clr-control-label">Running as user:</label>
<div class="mb-10 clr-control-container">
<div class="clr-input-wrapper">
<p class="mt-0">{{ runningAsUser }}</p>
</div>
</div>
</ng-container>
<!-- Keeping this for a reference in case future VIYA changes and starts allowing separate backend and frontend) --> <!-- Keeping this for a reference in case future VIYA changes and starts allowing separate backend and frontend) -->
<!-- <clr-checkbox-wrapper> <!-- <clr-checkbox-wrapper>

View File

@ -8,6 +8,7 @@ import {
} from '@angular/core' } from '@angular/core'
import SASjs, { SASjsConfig } from '@sasjs/adapter' import SASjs, { SASjsConfig } from '@sasjs/adapter'
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings' import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
import { HelperService } from 'src/app/services'
import { DeployService } from 'src/app/services/deploy.service' import { DeployService } from 'src/app/services/deploy.service'
import { EventService } from 'src/app/services/event.service' import { EventService } from 'src/app/services/event.service'
import { LoggerService } from 'src/app/services/logger.service' import { LoggerService } from 'src/app/services/logger.service'
@ -18,6 +19,11 @@ import {
Item, Item,
ViyaApiIdentities ViyaApiIdentities
} from 'src/app/viya-api-explorer/models/viya-api-identities.model' } from 'src/app/viya-api-explorer/models/viya-api-identities.model'
import { ComputeContextDetails } from 'src/app/viya-api-explorer/models/viya-compute-context-details.model'
import {
ViyaComputeContexts,
Item as ComputeContextItem
} from 'src/app/viya-api-explorer/models/viya-compute-contexts.model'
@Component({ @Component({
selector: 'app-automatic-deploy', selector: 'app-automatic-deploy',
@ -35,6 +41,7 @@ export class AutomaticComponent implements OnInit {
@Output() onNavigateToHome: EventEmitter<any> = new EventEmitter<any>() @Output() onNavigateToHome: EventEmitter<any> = new EventEmitter<any>()
public selectedComputeContext: string = ''
public makeDataResponse: string = '' public makeDataResponse: string = ''
public jsonFile: any = null public jsonFile: any = null
public autodeploying: boolean = false public autodeploying: boolean = false
@ -50,8 +57,11 @@ export class AutomaticComponent implements OnInit {
public createDatabaseLoading: boolean = false public createDatabaseLoading: boolean = false
public adminGroupsLoading: boolean = false public adminGroupsLoading: boolean = false
public currentUserInfoLoading: boolean = false public currentUserInfoLoading: boolean = false
public computeContextsLoading: boolean = false
public adminGroups: { id: string; name: string }[] = [] public adminGroups: { id: string; name: string }[] = []
public runningAsUser: string | undefined
public currentUserInfo: ViyaApiCurrentUser | null = null public currentUserInfo: ViyaApiCurrentUser | null = null
public computeContexts: ComputeContextItem[] = []
/** autoDeployStatus /** autoDeployStatus
* This object presents the status for two steps that we have for deploy. * This object presents the status for two steps that we have for deploy.
@ -73,46 +83,122 @@ export class AutomaticComponent implements OnInit {
private deployService: DeployService, private deployService: DeployService,
private sasService: SasService, private sasService: SasService,
private sasViyaService: SasViyaService, private sasViyaService: SasViyaService,
private loggerService: LoggerService private loggerService: LoggerService,
private helperService: HelperService
) {} ) {}
ngOnInit(): void { ngOnInit(): void {
this.getAdminGroups() this.loadData()
this.getCurrentUser() }
public async loadData() {
await this.getAdminGroups()
await this.getComputeContexts()
await this.getCurrentUser()
setTimeout(() => {
if (this.selectedComputeContext) {
this.onComputeContextChange(this.selectedComputeContext)
}
}, 500)
}
public async getComputeContexts() {
return new Promise<void>((resolve, reject) => {
this.computeContextsLoading = true
this.sasViyaService.getComputeContexts().subscribe(
(res: ViyaComputeContexts) => {
this.computeContextsLoading = false
const defaultContext = res.items.find(
(item: ComputeContextItem) =>
item.name === 'SAS Job Execution compute context'
)
if (defaultContext) {
this.selectedComputeContext = defaultContext.id
}
this.computeContexts = res.items
resolve()
},
(err) => {
reject(err)
}
)
})
} }
public async getCurrentUser() { public async getCurrentUser() {
this.currentUserInfoLoading = true return new Promise<void>((resolve, reject) => {
this.currentUserInfoLoading = true
this.sasViyaService this.sasViyaService.getCurrentUser().subscribe(
.getCurrentUser() (res: ViyaApiCurrentUser) => {
.subscribe((res: ViyaApiCurrentUser) => { this.currentUserInfoLoading = false
this.currentUserInfoLoading = false
this.currentUserInfo = res this.currentUserInfo = res
this.dcPath = `/export/viya/homes/${res.id}` this.dcPath = `/export/viya/homes/${res.id}`
})
resolve()
},
(err) => {
console.error('Error while getting current user', err)
reject(err)
}
)
})
} }
public async getAdminGroups() { public async getAdminGroups() {
this.adminGroupsLoading = true return new Promise<void>((resolve, reject) => {
this.adminGroupsLoading = true
this.sasViyaService.getAdminGroups().subscribe((res: ViyaApiIdentities) => { this.sasViyaService
this.adminGroupsLoading = false .getAdminGroups()
// Map admin groups with only needed fields .subscribe((res: ViyaApiIdentities) => {
this.adminGroups = res.items.map((item: Item) => { this.adminGroupsLoading = false
return { // Map admin groups with only needed fields
id: item.id, this.adminGroups = res.items.map((item: Item) => {
name: item.name return {
id: item.id,
name: item.name
}
})
resolve()
}),
(err: any) => {
this.adminGroupsLoading = false
this.loggerService.error('Error while getting admin groups', err)
this.eventService.showAbortModal('admin groups', err)
reject(err)
}
})
}
public async onComputeContextChange(computeContextId: string) {
this.sasViyaService
.getComputeContextById(computeContextId)
.subscribe((res: ComputeContextDetails) => {
if (res.attributes && res.attributes.runServerAs) {
this.runningAsUser = res.attributes.runServerAs
} else {
this.runningAsUser = this.currentUserInfo?.id || 'unknown'
} }
}) })
}), }
(err: any) => {
this.adminGroupsLoading = false public getComputeContextName(id: string): string | undefined {
this.loggerService.error('Error while getting admin groups', err) return (
this.eventService.showAbortModal('admin groups', err) this.computeContexts.find(
} (context: ComputeContextItem) => context.id === id
)?.name || undefined
)
} }
/** /**
@ -186,6 +272,19 @@ export class AutomaticComponent implements OnInit {
] ]
} }
// Get and run service using the selected context name
let selectedComputeContextName = this.sasJsConfig.contextName
if (this.selectedComputeContext.length && this.computeContexts.length) {
const computeContextName = this.getComputeContextName(
this.selectedComputeContext
)
if (computeContextName) {
selectedComputeContextName = computeContextName
}
}
/** /**
* We are overriding default `sasjsConfig` object fields with this object fields. * We are overriding default `sasjsConfig` object fields with this object fields.
* Here we want to run this request using original WEB method. * Here we want to run this request using original WEB method.
@ -193,7 +292,7 @@ export class AutomaticComponent implements OnInit {
*/ */
let overrideConfig = { let overrideConfig = {
useComputeApi: null, useComputeApi: null,
contextName: this.sasJsConfig.contextName, contextName: selectedComputeContextName,
debug: true debug: true
} }
@ -227,6 +326,9 @@ export class AutomaticComponent implements OnInit {
MAC: macMsg MAC: macMsg
}) })
} }
if (this.helperService.isStreamingViya())
this.updateIndexHtmlComputeContext()
}) })
.catch((err: any) => { .catch((err: any) => {
this.eventService.showAbortModal('makedata', JSON.stringify(err)) this.eventService.showAbortModal('makedata', JSON.stringify(err))
@ -241,6 +343,57 @@ export class AutomaticComponent implements OnInit {
}) })
} }
/**
* Only when on Viya streamed app, this method will update the `contextname` in the `index.html` on the SAS drive
* This is needed to ensure that the DC will use the same compute context `makedata` service used to run against.
*/
public async updateIndexHtmlComputeContext() {
const filenamePath = location.search.split('/').pop()
const filename = filenamePath?.includes('.') ? filenamePath : undefined
if (!filename) {
this.eventService.showAbortModal(
null,
'We could not figure out the file name of `index.html` based on the url.'
)
return
}
const indexHtmlContent = await this.sasService.getFileContent(
`${this.appLoc}/services`,
filename
)
if (!indexHtmlContent) {
this.loggerService.error(
`Failed to get ${filename} at ${this.appLoc}/services`
)
return
}
const computeContextName = this.getComputeContextName(
this.selectedComputeContext
)
if (!computeContextName) {
this.loggerService.error(
`Compute context name not found for ID: ${this.selectedComputeContext} | List: ${JSON.stringify(this.computeContexts)}`
)
return
}
const updatedContent = indexHtmlContent.replace(
/contextname="[^"]*"/g,
`contextname="${computeContextName}"`
)
await this.sasService
.updateFileContent(`${this.appLoc}/services`, filename, updatedContent)
.catch((err: any) => {
this.loggerService.error(`Failed to update DataController.html: ${err}`)
})
}
public downloadFile( public downloadFile(
content: any, content: any,
filename: string, filename: string,

View File

@ -8,4 +8,5 @@ export interface Libinfo {
LIBID: string LIBID: string
LIBSIZE: number LIBSIZE: number
TABLE_CNT: number TABLE_CNT: number
CATALOG_CNT: number
} }

View File

@ -1,30 +1,14 @@
import { BaseSASResponse } from './common/BaseSASResponse' import { BaseSASResponse } from './common/BaseSASResponse'
export interface EditorsStageDataSASResponse extends BaseSASResponse { export interface EditorsStageDataSASResponse extends BaseSASResponse {
SYSDATE: string
SYSTIME: string
sasparams: Sasparam[] sasparams: Sasparam[]
_DEBUG: string
_PROGRAM: string
AUTOEXEC: string AUTOEXEC: string
MF_GETUSER: string
SYSCC: string
SYSENCODING: string SYSENCODING: string
SYSERRORTEXT: string
SYSHOSTINFOLONG: string SYSHOSTINFOLONG: string
SYSHOSTNAME: string
SYSPROCESSID: string SYSPROCESSID: string
SYSPROCESSMODE: string SYSPROCESSMODE: string
SYSPROCESSNAME: string SYSPROCESSNAME: string
SYSJOBID: string
SYSSCPL: string
SYSSITE: string
SYSTCPIPHOSTNAME: string SYSTCPIPHOSTNAME: string
SYSUSERID: string
SYSVLONG: string
SYSWARNINGTEXT: string
END_DTTM: string
MEMSIZE: string
} }
export interface Sasparam { export interface Sasparam {

View File

@ -0,0 +1,28 @@
import { BaseSASResponse } from './common/BaseSASResponse'
export interface PublicGetChangeinfo extends BaseSASResponse {
jsparams: Jsparam[]
}
export interface Jsparam {
TABLE_ID: string
SUBMIT_STATUS_CD: string
BASE_LIB: string
BASE_DS: string
SUBMITTED_BY_NM: string
SUBMITTED_ON: number
SUBMITTED_REASON_TXT: string
INPUT_OBS: number
INPUT_VARS: number
NUM_OF_APPROVALS_REQUIRED: number
NUM_OF_APPROVALS_REMAINING: number
REVIEWED_BY_NM: string
REVIEWED_ON?: any
TABLE_NM: string
BASE_TABLE: string
REVIEWED_ON_DTTM: string
SUBMITTED_ON_DTTM: string
LIB_ENGINE: string
ALLOW_RESTORE: string
REASON: string
}

View File

@ -13,6 +13,8 @@ import {
AuditorsPostdataSASResponse, AuditorsPostdataSASResponse,
Param Param
} from '../../models/sas/auditors-postdata.model' } from '../../models/sas/auditors-postdata.model'
import { PublicGetChangeinfo } from 'src/app/models/sas/public-getchangeinfo.model'
import { SasService } from 'src/app/services'
interface ChangesObj { interface ChangesObj {
ind: any ind: any
@ -76,9 +78,11 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
public diffsLimit: boolean = false public diffsLimit: boolean = false
public recordsLimit: number = 100 public recordsLimit: number = 100
public refreshStartupserviceAfterApprove: boolean = false
constructor( constructor(
private sasStoreService: SasStoreService, private sasStoreService: SasStoreService,
private sasService: SasService,
private eventService: EventService, private eventService: EventService,
private router: ActivatedRoute, private router: ActivatedRoute,
private route: Router private route: Router
@ -162,6 +166,9 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
await this.sasStoreService await this.sasStoreService
.approveTable(approveParams, 'SASControlTable', 'auditors/postdata') .approveTable(approveParams, 'SASControlTable', 'auditors/postdata')
.then((res: any) => { .then((res: any) => {
// If we are approving MPE_TABLES we will arm the trigger for the reload of startup data to se the updated tables
if (this.refreshStartupserviceAfterApprove)
this.sasService.reloadStartupData()
this.route.navigateByUrl('/review/history') this.route.navigateByUrl('/review/history')
}) })
.catch((err: any) => { .catch((err: any) => {
@ -176,7 +183,7 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
public async callChangesInfo(tableId: any) { public async callChangesInfo(tableId: any) {
await this.sasStoreService await this.sasStoreService
.getChangeInfo(tableId) .getChangeInfo(tableId)
.then((res: any) => { .then((res: PublicGetChangeinfo) => {
this.tableDetails = res.jsparams[0] this.tableDetails = res.jsparams[0]
this.jsParams = res.jsparams[0] this.jsParams = res.jsparams[0]
@ -189,6 +196,11 @@ export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
} }
this.keysArray = keysArray this.keysArray = keysArray
// If we are approving MPE_TABLES we will arm the trigger for the reload of startup data to se the updated tables
// After user approved if armed, reload will be triggered
if (res.jsparams[0].BASE_DS === 'MPE_TABLES')
this.refreshStartupserviceAfterApprove = true
}) })
.catch((err: any) => { .catch((err: any) => {
this.acceptLoading = false this.acceptLoading = false

View File

@ -1,6 +1,7 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import cloneDeep from 'lodash-es/cloneDeep' import cloneDeep from 'lodash-es/cloneDeep'
import * as CryptoMD5 from 'crypto-js/md5' import * as CryptoMD5 from 'crypto-js/md5'
import { SasService } from './sas.service'
const librariesToShow = 50 const librariesToShow = 50
@ -12,7 +13,7 @@ export class HelperService {
public loadMoreCount: number = librariesToShow public loadMoreCount: number = librariesToShow
public isMicrosoft: boolean = false public isMicrosoft: boolean = false
constructor() { constructor(private sasService: SasService) {
this.isMicrosoft = this.isIEorEDGE() this.isMicrosoft = this.isIEorEDGE()
console.log('Is IE or Edge?', this.isMicrosoft) console.log('Is IE or Edge?', this.isMicrosoft)
} }
@ -314,6 +315,20 @@ export class HelperService {
} }
} }
public isStreamingViya(): boolean {
const serverType = this.sasService.getServerType()
if (serverType !== 'SASVIYA') return false
if (
location.search.toLowerCase().includes('?_file=') &&
location.pathname.toLowerCase().includes('/sasjobexecution')
)
return true
return false
}
// Required type is NodeJS.Timeout // Required type is NodeJS.Timeout
// But NodeJS is not available in browser so we have to go with any // But NodeJS is not available in browser so we have to go with any
private debounceTimeout: any private debounceTimeout: any

View File

@ -1,6 +1,12 @@
import { HttpClient } from '@angular/common/http' import {
HttpClient,
HttpContext,
HttpErrorResponse,
HttpHeaders,
HttpParams
} from '@angular/common/http'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { Observable } from 'rxjs' import { catchError, Observable, throwError } from 'rxjs'
import { Collection } from '../viya-api-explorer/models/collection.model' import { Collection } from '../viya-api-explorer/models/collection.model'
import { AppStoreService } from './app-store.service' import { AppStoreService } from './app-store.service'
import { ViyaApis } from '../viya-api-explorer/models/viya-apis.models' import { ViyaApis } from '../viya-api-explorer/models/viya-apis.models'
@ -8,6 +14,8 @@ import { ViyaApiFolderMembers } from '../viya-api-explorer/models/viya-api-folde
import { ViyaApiFolder } from '../viya-api-explorer/models/viya-api-folder.model' import { ViyaApiFolder } from '../viya-api-explorer/models/viya-api-folder.model'
import { ViyaApiIdentities } from '../viya-api-explorer/models/viya-api-identities.model' import { ViyaApiIdentities } from '../viya-api-explorer/models/viya-api-identities.model'
import { ViyaApiCurrentUser } from '../viya-api-explorer/models/viya-api-current-user.model' import { ViyaApiCurrentUser } from '../viya-api-explorer/models/viya-api-current-user.model'
import { ViyaComputeContexts } from '../viya-api-explorer/models/viya-compute-contexts.model'
import { ComputeContextDetails } from '../viya-api-explorer/models/viya-compute-context-details.model'
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -75,7 +83,7 @@ export class SasViyaService {
this.serverUrl = adapterConfig?.serverUrl || '' this.serverUrl = adapterConfig?.serverUrl || ''
//example collection request // example collection request
// this.getByCollection('jobs').subscribe((res) => { // this.getByCollection('jobs').subscribe((res) => {
// console.log('res', res) // console.log('res', res)
// }) // })
@ -95,7 +103,7 @@ export class SasViyaService {
* @returns * @returns
*/ */
getByUrl(url: string): Observable<Collection> { getByUrl(url: string): Observable<Collection> {
return this.http.get<Collection>(`${this.serverUrl}${url}`, { return this.get<Collection>(`${this.serverUrl}${url}`, {
withCredentials: true withCredentials: true
}) })
} }
@ -106,23 +114,32 @@ export class SasViyaService {
* @returns * @returns
*/ */
getByCollection(apiCollection: string): Observable<Collection> { getByCollection(apiCollection: string): Observable<Collection> {
return this.http.get<Collection>(`${this.serverUrl}${apiCollection}`, { return this.get<Collection>(`${this.serverUrl}${apiCollection}`, {
withCredentials: true withCredentials: true
}) })
} }
getComputeContexts(): Observable<any> { getComputeContexts(): Observable<ViyaComputeContexts> {
return this.http.get<any>(`${this.serverUrl}/compute/contexts`, { return this.get<ViyaComputeContexts>(`${this.serverUrl}/compute/contexts`, {
withCredentials: true withCredentials: true
}) })
} }
getComputeContextById(id: string): Observable<ComputeContextDetails> {
return this.get<ComputeContextDetails>(
`${this.serverUrl}/compute/contexts/${id}`,
{
withCredentials: true
}
)
}
/** /**
* @param path Path to the folder * @param path Path to the folder
* @returns The folder info object * @returns The folder info object
*/ */
getFolderByPath(path: string): Observable<ViyaApiFolder> { getFolderByPath(path: string): Observable<ViyaApiFolder> {
return this.http.get<ViyaApiFolder>( return this.get<ViyaApiFolder>(
`${this.serverUrl}/folders/folders/@item?path=${path}`, `${this.serverUrl}/folders/folders/@item?path=${path}`,
{ {
withCredentials: true withCredentials: true
@ -131,7 +148,7 @@ export class SasViyaService {
} }
getFolderMembers(folderId: string): Observable<ViyaApiFolderMembers> { getFolderMembers(folderId: string): Observable<ViyaApiFolderMembers> {
return this.http.get<ViyaApiFolderMembers>( return this.get<ViyaApiFolderMembers>(
`${this.serverUrl}/folders/folders/${folderId}/members`, `${this.serverUrl}/folders/folders/${folderId}/members`,
{ {
withCredentials: true withCredentials: true
@ -140,7 +157,7 @@ export class SasViyaService {
} }
getAdminGroups(limit: number = 5000): Observable<ViyaApiIdentities> { getAdminGroups(limit: number = 5000): Observable<ViyaApiIdentities> {
return this.http.get<ViyaApiIdentities>( return this.get<ViyaApiIdentities>(
`${this.serverUrl}/identities/groups?sortBy=name&limit=${limit}`, `${this.serverUrl}/identities/groups?sortBy=name&limit=${limit}`,
{ {
withCredentials: true withCredentials: true
@ -149,11 +166,54 @@ export class SasViyaService {
} }
getCurrentUser(): Observable<ViyaApiCurrentUser> { getCurrentUser(): Observable<ViyaApiCurrentUser> {
return this.http.get<ViyaApiCurrentUser>( return this.get<ViyaApiCurrentUser>(
`${this.serverUrl}/identities/users/@currentUser`, `${this.serverUrl}/identities/users/@currentUser`,
{ {
withCredentials: true withCredentials: true
} }
) )
} }
get<T>(
url: string,
options?: {
headers?:
| HttpHeaders
| {
[header: string]: string | string[]
}
context?: HttpContext
observe?: 'body'
params?:
| HttpParams
| {
[param: string]:
| string
| number
| boolean
| ReadonlyArray<string | number | boolean>
}
reportProgress?: boolean
responseType?: 'json'
withCredentials?: boolean
transferCache?:
| {
includeHeaders?: string[]
}
| boolean
}
): Observable<T> {
return this.http.get<T>(url, options).pipe(
catchError((err: HttpErrorResponse) => {
console.log('url', url)
console.log('err.status', err.status)
if (err.status === 449 || err.status === 401) {
// Retry once if we got a 449
return this.http.get<T>(url, options)
}
// Otherwise propagate the error
return throwError(() => err)
})
)
}
} }

View File

@ -333,6 +333,10 @@ export class SasService {
}) })
} }
public reloadStartupData() {
this.loadStartupServiceEmitter.emit()
}
public getLicenseSiteId(): string[] { public getLicenseSiteId(): string[] {
return this.license_site_id.value || [] return this.license_site_id.value || []
} }
@ -657,4 +661,17 @@ export class SasService {
} }
} }
} }
// Viya specific functions
public getFileContent(folderPath: string, fileName: string) {
return this.sasjsAdapter.getFileContent(folderPath, fileName)
}
public updateFileContent(
folderPath: string,
fileName: string,
content: string
) {
return this.sasjsAdapter.updateFileContent(folderPath, fileName, content)
}
} }

View File

@ -598,6 +598,12 @@
{{ libinfo[0] ? libinfo[0].TABLE_CNT : '' }} {{ libinfo[0] ? libinfo[0].TABLE_CNT : '' }}
</td> </td>
</tr> </tr>
<tr *ngIf="libinfo[0].CATALOG_CNT !== null">
<td class="m-0">CATALOG_CNT:</td>
<td class="m-0 font-bold">
{{ libinfo[0] ? libinfo[0].CATALOG_CNT : '' }}
</td>
</tr>
</table> </table>
</ng-container> </ng-container>
</div> </div>

View File

@ -0,0 +1,34 @@
export interface ComputeContextDetails {
attributes?: Attributes
createdBy: string
creationTimeStamp: string
description: string
id: string
launchContext: LaunchContext
launchType: string
links: Link[]
modifiedBy: string
modifiedTimeStamp: string
name: string
version: number
}
export interface Link {
method: string
rel: string
href: string
uri: string
type?: string
responseType?: string
itemType?: string
}
export interface LaunchContext {
contextId: string
}
export interface Attributes {
reuseServerProcesses: string
runServerAs: string
serverMinAvailable: string
}

View File

@ -0,0 +1,36 @@
export interface ViyaComputeContexts {
accept: string
count: number
items: Item[]
limit: number
links: Link2[]
name: string
start: number
version: number
}
export interface Link2 {
method: string
rel: string
href: string
uri: string
type: string
itemType: string
}
export interface Item {
createdBy: string
id: string
links: Link[]
name: string
version: number
}
export interface Link {
method: string
rel: string
href: string
uri: string
type?: string
responseType?: string
}

View File

@ -3884,6 +3884,12 @@ app-header-actions {
// END OF CSP WORKAROUND // END OF CSP WORKAROUND
.clr-input-wrapper.small-mt {
.clr-form-control {
margin-top: 5px !important;
}
}
body[cds-theme="dark"] { body[cds-theme="dark"] {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: $trackColor $thumbColor; scrollbar-color: $trackColor $thumbColor;

View File

@ -1,6 +1,6 @@
{ {
"name": "dcfrontend", "name": "dcfrontend",
"version": "6.14.10", "version": "7.0.1",
"description": "Data Controller", "description": "Data Controller",
"devDependencies": { "devDependencies": {
"@saithodev/semantic-release-gitea": "^2.1.0", "@saithodev/semantic-release-gitea": "^2.1.0",
@ -19,7 +19,9 @@
"lint": "npm run lint:fix", "lint": "npm run lint:fix",
"lint:fix": "npx prettier --write \"client/{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\" \"client/cypress/integration/*.tests.ts\"", "lint:fix": "npx prettier --write \"client/{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\" \"client/cypress/integration/*.tests.ts\"",
"lint:check": "npx prettier --check \"client/{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\" \"client/cypress/integration/*.tests.ts\"", "lint:check": "npx prettier --check \"client/{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\" \"client/cypress/integration/*.tests.ts\"",
"jo": "echo" "lint:silent": "npx prettier --loglevel silent --check \"client/{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\" \"client/cypress/integration/*.tests.ts\"",
"jo": "echo",
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks && git config core.autocrlf false || true"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

32
sas/package-lock.json generated
View File

@ -6,8 +6,8 @@
"": { "": {
"name": "dc-sas", "name": "dc-sas",
"dependencies": { "dependencies": {
"@sasjs/cli": "^4.12.5", "@sasjs/cli": "^4.12.8",
"@sasjs/core": "^4.58.1" "@sasjs/core": "^4.59.1"
} }
}, },
"node_modules/@coolaj86/urequest": { "node_modules/@coolaj86/urequest": {
@ -30,9 +30,9 @@
} }
}, },
"node_modules/@sasjs/adapter": { "node_modules/@sasjs/adapter": {
"version": "4.11.3", "version": "4.12.1",
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-4.11.3.tgz", "resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-4.12.1.tgz",
"integrity": "sha512-KF6G4vzs4l4efjpCD02og3kB44uFfJ1u2UWu749VdHtLKNN9l+PO26/moR+YAmRmmz2I9sC3X09fZE1nlN6zgw==", "integrity": "sha512-0217oZIkrecOyQygRe6Azgc1C4TIcjB5noi15fU4Rd5GsfDpleKVfQQdzYZ7im/vesWlLIVl/yUT67MMaQe0ew==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -45,14 +45,14 @@
} }
}, },
"node_modules/@sasjs/cli": { "node_modules/@sasjs/cli": {
"version": "4.12.5", "version": "4.12.8",
"resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-4.12.5.tgz", "resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-4.12.8.tgz",
"integrity": "sha512-y6JFATKlTyTl0gRPpDBPL1rwZsyeuyp5uEz7HMA7raSzQuNa6QZ1oO1Er91I7+cLUg0Ndh5aSNGKYOdBRStQ2g==", "integrity": "sha512-20WiywlcLV22T1XfkAumV66mM3PfQ1N9ihJfpxoOVCFs2wF/ZertqnP4BZ5CE1dc30M1C2oDOzzSSVZqePPQnw==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@sasjs/adapter": "4.11.3", "@sasjs/adapter": "4.12.1",
"@sasjs/core": "4.57.0", "@sasjs/core": "4.59.1",
"@sasjs/lint": "2.4.3", "@sasjs/lint": "2.4.3",
"@sasjs/utils": "3.5.2", "@sasjs/utils": "3.5.2",
"adm-zip": "0.5.10", "adm-zip": "0.5.10",
@ -76,16 +76,10 @@
"sasjs": "build/index.js" "sasjs": "build/index.js"
} }
}, },
"node_modules/@sasjs/cli/node_modules/@sasjs/core": {
"version": "4.57.0",
"resolved": "https://registry.npmjs.org/@sasjs/core/-/core-4.57.0.tgz",
"integrity": "sha512-iJiLnW4oY15InGerXXWtrjc1YpJ9UDz72+r7Odfr/yYR7RxIhtXGjYQIqyQu6US+cS/0b2pi12LZB6VnfMS/pA==",
"license": "MIT"
},
"node_modules/@sasjs/core": { "node_modules/@sasjs/core": {
"version": "4.58.1", "version": "4.59.1",
"resolved": "https://registry.npmjs.org/@sasjs/core/-/core-4.58.1.tgz", "resolved": "https://registry.npmjs.org/@sasjs/core/-/core-4.59.1.tgz",
"integrity": "sha512-Qp6KAtp1VZcmN5HLGSIUE9H41qpFuihWLbjNygOYp+NRs/Y8VagpHrYeyIQbh3cSgchiJEMXudLql8hoU06wpg==", "integrity": "sha512-52GNI4nIll5YivI8uobWrucE6TkHcTjcbKTr/YPC9eTauC4sh0V0MptebfAJ5E6vE5P2WevNZGr42KdDpckLpg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@sasjs/lint": { "node_modules/@sasjs/lint": {

View File

@ -22,13 +22,13 @@
"serverdata": "sasjs request services/admin/makedata -d deploy/makeDataServer.json -l sasjsresults/makedata_server.log -o sasjsresults/makedata_server.json -t server", "serverdata": "sasjs request services/admin/makedata -d deploy/makeDataServer.json -l sasjsresults/makedata_server.log -o sasjsresults/makedata_server.json -t server",
"viya": "npm run viyacbd && sasjs test", "viya": "npm run viyacbd && sasjs test",
"viyacbd": "sasjs folder delete /Public/app/viya && sasjs cbd -t viya && npm run viyadata", "viyacbd": "sasjs folder delete /Public/app/viya && sasjs cbd -t viya && npm run viyadata",
"viyadata": "sasjs request services/admin/makedata -d deploy/makeDataViya.json -l sasjsresults/makedata.log -o sasjsresults/output.json", "viyadata": "sasjs request services/admin/makedata -d deploy/makeDataViya.json -l sasjsresults/makedata.log -o sasjsresults/output.json -t viya",
"v4data": "sasjs request services/admin/makedata -d deploy/makeDataV4.json -l sasjsresults/makedatav4.log -o sasjsresults/outputv4.json -t v4", "v4data": "sasjs request services/admin/makedata -d deploy/makeDataV4.json -l sasjsresults/makedatav4.log -o sasjsresults/outputv4.json -t v4",
"sasdocs": "sasjs doc && ./sasjs/utils/deploydocs.sh" "sasdocs": "sasjs doc && ./sasjs/utils/deploydocs.sh"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@sasjs/cli": "^4.12.5", "@sasjs/cli": "^4.12.8",
"@sasjs/core": "^4.58.1" "@sasjs/core": "^4.59.1"
} }
} }

View File

@ -0,0 +1,17 @@
/**
@file mpe_datacatalog_CATS.ddl
@brief ddl file
@details
@version 9.3
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd
**/
create table &curlib..mpe_datacatalog_CATS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
constraint pk_mpe_datacatalog_CATS
primary key(libref,memname,tx_to));

View File

@ -0,0 +1,21 @@
/**
@file mpe_datacatalog_CATS.ddl
@brief ddl file
@details
@version 9.3
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd
**/
create table &curlib..mpe_datacatalog_OBJS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
objname char(32) label='Object Name',
objtype char(8) label='Object Type',
objdesc char(256) label='Object Description',
alias char(32) label='Object Alias',
constraint pk_mpe_datacatalog_OBJS
primary key(libref,memname,objname,objtype,tx_to));

View File

@ -0,0 +1,20 @@
/**
@file mpe_datacatalog_CATS.ddl
@brief ddl file
@details
@version 9.3
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd
**/
create table &curlib..mpe_datastatus_CATS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
nobjs num label='Number of objects',
created num format=DATETIME. label='Date Created',
modified num format=DATETIME. label='Date Modified',
constraint pk_mpe_datastatus_CATS
primary key(libref,memname,tx_to));

View File

@ -14,5 +14,6 @@ create table &curlib..mpe_datastatus_libs(
libref char(8) label='Library Name', libref char(8) label='Library Name',
libsize num format=SIZEKMG. label='Size of file', libsize num format=SIZEKMG. label='Size of file',
table_cnt num label='Number of Tables', table_cnt num label='Number of Tables',
catalog_cnt num label='Number of Catalogs',
constraint pk_mpe_datastatus_libs constraint pk_mpe_datastatus_libs
primary key(libref,tx_to)); primary key(libref,tx_to));

View File

@ -0,0 +1,22 @@
/**
@file mpe_datacatalog_CATS.ddl
@brief ddl file
@details
@version 9.3
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd
**/
create table &curlib..mpe_datastatus_OBJS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
objname char(32) label='Object Name',
objtype char(8) label='Object Type',
created num format=DATETIME. label='Date Created',
modified num format=DATETIME. label='Date Modified',
level num label='Library Concatenation Level',
constraint pk_mpe_datastatus_OBJS
primary key(libref,memname,objname,objtype,tx_to));

View File

@ -14,8 +14,8 @@ create table &curlib..mpe_datastatus_tabs(
libref char(8) label='Library Name', libref char(8) label='Library Name',
dsn char(64) label='Member Name', dsn char(64) label='Member Name',
filesize num format=SIZEKMG. label='Size of file', filesize num format=SIZEKMG. label='Size of file',
crdate num format=DATETIME. informat=DATETIME. label='Date Created', crdate num format=DATETIME. label='Date Created',
modate num format=DATETIME. informat=DATETIME. label='Date Modified', modate num format=DATETIME. label='Date Modified',
nobs num label='Number of Physical (Actual, inc. deleted) Observations', nobs num label='Number of Physical (Actual, inc. deleted) Observations',
constraint pk_mpe_datastatus_tabs constraint pk_mpe_datastatus_tabs
primary key(libref,dsn,tx_to)); primary key(libref,dsn,tx_to));

View File

@ -29,7 +29,7 @@ create table dc.mpe_datacatalog_TABS(
nvar num label='Number of Variables', nvar num label='Number of Variables',
compress char(8) label='Compression Routine', compress char(8) label='Compression Routine',
pk_fields char(512) pk_fields char(512)
label='Primary Key Fields (identified by being in a constraint that is both Unique and Not Null)', label='Primary Key Fields (in a constraint that is both Unique and Not Null)',
constraint pk constraint pk
primary key(libref,dsn,tx_to)); primary key(libref,dsn,tx_to));
@ -67,8 +67,8 @@ create table dc.mpe_datacatalog_vars(
libref char(8) label='Library Name', libref char(8) label='Library Name',
dsn char(64) label='Member Name', dsn char(64) label='Member Name',
filesize num format=SIZEKMG. label='Size of file', filesize num format=SIZEKMG. label='Size of file',
crdate num format=DATETIME. informat=DATETIME. label='Date Created', crdate num format=DATETIME. label='Date Created',
modate num format=DATETIME. informat=DATETIME. label='Date Modified', modate num format=DATETIME. label='Date Modified',
nobs num label='Number of Physical (Actual, inc. deleted) Observations', nobs num label='Number of Physical (Actual, inc. deleted) Observations',
constraint pk constraint pk
primary key(libref,dsn,tx_to)); primary key(libref,dsn,tx_to));

View File

@ -0,0 +1,71 @@
/**
@file
@brief migration script to move from v6.8.2 to v7.0 of data controller
BREAKING CHANGE - 1 new column and 4 additional tables for capturing catalogs
Be sure to run this using the correct system account
(eg the regular DC account)
On SAS 9 you may wish to run proc metalib or refresh in DI Studio afterwards
to see the new tables in the VIEW page
proc metalib;
omr (library="&DC_LIBNAME");
folder="&root/data";
update_rule=(delete);
run;
**/
%let dclib=YOURDCLIB;
libname &dclib "/YOUR/DATACONTROLLER/LIBRARY/PATH";
proc sql;
create table work.BACKUP as select * from &dclib..mpe_datastatus_libs;
alter table &dclib..mpe_datastatus_libs add catalog_cnt num;
create table &dclib..mpe_datacatalog_CATS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
constraint pk_mpe_datacatalog_CATS
primary key(libref,memname,tx_to));
create table &dclib..mpe_datacatalog_OBJS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
objname char(32) label='Object Name',
objtype char(8) label='Object Type',
objdesc char(256) label='Object Description',
alias char(32) label='Object Alias',
constraint pk_mpe_datacatalog_OBJS
primary key(libref,memname,objname,objtype,tx_to));
create table &dclib..mpe_datastatus_CATS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
nobjs num label='Number of objects',
created num format=DATETIME. label='Date Created',
modified num format=DATETIME. label='Date Modified',
constraint pk_mpe_datastatus_CATS
primary key(libref,memname,tx_to));
create table &dclib..mpe_datastatus_OBJS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
objname char(32) label='Object Name',
objtype char(8) label='Object Type',
created num format=DATETIME. label='Date Created',
modified num format=DATETIME. label='Date Modified',
level num label='Library Concatenation Level',
constraint pk_mpe_datastatus_OBJS
primary key(libref,memname,objname,objtype,tx_to));

View File

@ -14,14 +14,31 @@
**/ **/
%macro mpe_dsmeta(libds, outds=dsmeta); %macro mpe_dsmeta(libds, outds=dsmeta);
%local ddsd ddld notes lenstmt; %local ddsd ddld notes lenstmt memname;
%let lenstmt=length ods_table $18 name $100 value $1000; %let lenstmt=length ods_table $18 name $100 value $1000;
%let libds=%upcase(&libds); %let libds=%upcase(&libds);
%mp_dsmeta(&libds, outds=&outds)
%if "%scan(&libds,2,-)" ne "FC" %then %do;
%let memname=%scan(&libds,2,.);
%mp_dsmeta(&libds, outds=&outds)
%end;
%else %do;
%let memname=%scan(&libds,2,.-);
data &outds;
&lenstmt;
set sashelp.vcatalg;
ods_table=cats(objtype);
name=cats(objname);
value=catx(' ',objdesc,'(modified:',put(modified,datetime19.),')');
where libname="%scan(&libds,1,.)" and memname="&memname";
keep ods_table name value;
run;
proc sort; by ods_table name;run;
%end;
data _null_; data _null_;
set &mpelib..mpe_datadictionary; set &mpelib..mpe_datadictionary;
where &dc_dttmtfmt < tx_to & dd_source=%upcase("&libds") & dd_type='TABLE'; where &dc_dttmtfmt < tx_to & dd_source="&memname" & dd_type='TABLE';
call symputx('ddsd',dd_shortdesc,'l'); call symputx('ddsd',dd_shortdesc,'l');
call symputx('ddld',dd_longdesc,'l'); call symputx('ddld',dd_longdesc,'l');
run; run;

View File

@ -34,4 +34,15 @@ run;
outds=work.test_results outds=work.test_results
) )
%mpe_dsmeta(FMTONLY.DCFMTS-FC,outds=test2)
data work.test2;
set work.test2;
putlog (_all_)(=);
run;
%mp_assertdsobs(work.test2,
desc=Test 2 - records returned,
test=EQUALS 5,
outds=work.test_results
)

View File

@ -106,6 +106,19 @@ proc datasets lib=&lib noprint;
/nomiss unique; /nomiss unique;
quit; quit;
proc sql; proc sql;
create table &lib..mpe_datacatalog_CATS(
TX_FROM float &notnull format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name'
);quit;
proc datasets lib=&lib noprint;
modify mpe_datacatalog_CATS;
index create
pk_mpe_datacatalog_CATS=(tx_to libref memname)
/nomiss unique;
quit;
proc sql;
create table &lib..mpe_datacatalog_libs( create table &lib..mpe_datacatalog_libs(
TX_FROM num &notnull format=datetime19.3, TX_FROM num &notnull format=datetime19.3,
TX_TO num &notnull format=datetime19.3, TX_TO num &notnull format=datetime19.3,
@ -125,6 +138,23 @@ proc datasets lib=&lib noprint;
/nomiss unique; /nomiss unique;
quit; quit;
proc sql; proc sql;
create table &lib..mpe_datacatalog_OBJS(
TX_FROM num &notnull format=datetime19.,
TX_TO num &notnull format=datetime19.,
libref char(8) &notnull label='Library Name',
memname char(64) &notnull label='Member Name',
objname char(32) &notnull label='Object Name',
objtype char(8) &notnull label='Object Type',
objdesc char(256) label='Object Description',
alias char(32) label='Object Alias'
);quit;
proc datasets lib=&lib noprint;
modify mpe_datacatalog_OBJS;
index create
pk_mpe_datacatalog_OBJS=(libref memname objname objtype tx_to)
/nomiss unique;
quit;
proc sql;
create table &lib..mpe_datacatalog_TABS( create table &lib..mpe_datacatalog_TABS(
TX_FROM num &notnull format=datetime19.3, TX_FROM num &notnull format=datetime19.3,
TX_TO num &notnull format=datetime19.3, TX_TO num &notnull format=datetime19.3,
@ -137,7 +167,7 @@ create table &lib..mpe_datacatalog_TABS(
nvar num label='Number of Variables', nvar num label='Number of Variables',
compress char(8) label='Compression Routine', compress char(8) label='Compression Routine',
pk_fields char(512) pk_fields char(512)
label='Primary Key Fields (identified by being in a constraint that is both Unique and Not Null)' label='Primary Key Fields - in a constraint being both Unique and Not Null'
);quit; );quit;
proc datasets lib=&lib noprint; proc datasets lib=&lib noprint;
modify mpe_datacatalog_TABS; modify mpe_datacatalog_TABS;
@ -169,12 +199,29 @@ proc datasets lib=&lib noprint;
/nomiss unique; /nomiss unique;
quit; quit;
proc sql; proc sql;
create table &lib..mpe_datastatus_CATS(
TX_FROM float format=datetime19.,
TX_TO float format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
nobjs num &notnull label='Number of objects',
created num &notnull format=DATETIME. label='Date Created',
modified num format=DATETIME. label='Date Modified'
);quit;
proc datasets lib=&lib noprint;
modify mpe_datastatus_CATS;
index create
pk_mpe_datastatus_cats=(libref memname tx_to)
/nomiss unique;
quit;
proc sql;
create table &lib..mpe_datastatus_libs( create table &lib..mpe_datastatus_libs(
TX_FROM num &notnull format=datetime19.3, TX_FROM num &notnull format=datetime19.3,
TX_TO num &notnull format=datetime19.3, TX_TO num &notnull format=datetime19.3,
libref char(8) label='Library Name', libref char(8) label='Library Name',
libsize num format=SIZEKMG. label='Size of library', libsize num format=SIZEKMG. label='Size of library',
table_cnt num label='Number of Tables' table_cnt num label='Number of Tables',
catalog_cnt num label='Number of Catalogs'
);quit; );quit;
proc datasets lib=&lib noprint; proc datasets lib=&lib noprint;
modify mpe_datastatus_libs; modify mpe_datastatus_libs;
@ -183,14 +230,32 @@ proc datasets lib=&lib noprint;
/nomiss unique; /nomiss unique;
quit; quit;
proc sql; proc sql;
create table &lib..mpe_datastatus_OBJS(
TX_FROM float &notnull format=datetime19.,
TX_TO float &notnull format=datetime19.,
libref char(8) label='Library Name',
memname char(64) label='Member Name',
objname char(32) label='Object Name',
objtype char(8) label='Object Type',
created num &notnull format=DATETIME. label='Date Created',
modified num format=DATETIME. label='Date Modified',
level num label='Library Concatenation Level'
);quit;
proc datasets lib=&lib noprint;
modify mpe_datastatus_OBJS;
index create
pk_mpe_datastatus_OBJS=(libref memname objname objtype tx_to)
/nomiss unique;
quit;
proc sql;
create table &lib..mpe_datastatus_tabs( create table &lib..mpe_datastatus_tabs(
TX_FROM num &notnull format=datetime19.3, TX_FROM num &notnull format=datetime19.3,
TX_TO num &notnull format=datetime19.3, TX_TO num &notnull format=datetime19.3,
libref char(8) label='Library Name', libref char(8) label='Library Name',
dsn char(64) label='Member Name', dsn char(64) label='Member Name',
filesize num format=SIZEKMG. label='Size of file', filesize num format=SIZEKMG. label='Size of file',
crdate num format=DATETIME. informat=DATETIME. label='Date Created', crdate num format=DATETIME. label='Date Created',
modate num format=DATETIME. informat=DATETIME. label='Date Modified', modate num format=DATETIME. label='Date Modified',
nobs num label='Number of Physical (Actual, inc. deleted) Observations' nobs num label='Number of Physical (Actual, inc. deleted) Observations'
);quit; );quit;
proc datasets lib=&lib noprint; proc datasets lib=&lib noprint;

View File

@ -0,0 +1,26 @@
/**
@file
@brief Testing mpe_refreshtables macro
<h4> SAS Macros </h4>
@li mpe_makedatamodel.sas
@li mp_assert.sas
@li mp_assertscope.sas
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
and may not be re-distributed or re-sold without the express permission of
4GL Apps Ltd.
**/
%mp_assertscope(SNAPSHOT)
%mpe_makedatamodel(lib=WORK)
%mp_assertscope(COMPARE,
desc=Checking macro variables against previous snapshot
)
%mp_assert(
iftrue=(&syscc = 0),
desc=Checking error condition
)

View File

@ -0,0 +1,140 @@
/**
@file mpe_refreshtables.sas
@brief Refreshes the data catalog
@details Assumes library is already assigned.
Usage:
%mpe_refreshcatalogs(sashelp)
<h4> SAS Macros </h4>
@li bitemporal_dataloader.sas
@version 9.3
@author 4GL Apps Ltd
**/
%macro mpe_refreshcatalogs(lib,cat=#all);
%let lib=%upcase(&lib);
%let cat=%upcase(&cat);
%put running &sysmacroname &lib for &cat;
proc sql;
create table work.catdata as
select libname as libref,
memname,
objname,
objtype,
objdesc,
created,
modified,
alias,
level
from dictionary.catalogs
where upcase(libname)="&lib"
%if &cat ne #ALL %then %do;
and upcase(memname)="&cat"
%end;
;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(syscc=&syscc afer &lib objects extraction)
)
/* load mpe_datacatalog_CATS */
proc sql;
create table datacats as select distinct libref,memname from catdata;
%bitemporal_dataloader(base_lib=&mpelib
,base_dsn=mpe_datacatalog_CATS
,append_dsn=datacats
,PK=LIBREF MEMNAME
,etlsource=&sysmacroname
,loadtype=TXTEMPORAL
,tech_from=TX_FROM
,tech_to=TX_TO
%if &cat = #ALL %then %do;
,close_vars=LIBREF
%end;
,dclib=&mpelib
)
/* load mpe_datacatalog_objsS */
proc sql;
create table dataobjs as
select distinct libref,
memname,
objname,
objtype,
objdesc,
alias
from catdata;
quit;
%bitemporal_dataloader(base_lib=&mpelib
,base_dsn=mpe_datacatalog_OBJS
,append_dsn=dataobjs
,PK=LIBREF MEMNAME OBJNAME OBJTYPE
,etlsource=&sysmacroname
,loadtype=TXTEMPORAL
,tech_from=TX_FROM
,tech_to=TX_TO
%if &cat = #ALL %then %do;
,close_vars=LIBREF MEMNAME
%end;
,dclib=&mpelib
)
%put load mpe_datastatus_OBJS;
proc sql;
create table statusobjs as
select distinct libref,
memname,
objname,
objtype,
created,
modified,
level
from catdata;
%bitemporal_dataloader(base_lib=&mpelib
,base_dsn=mpe_datastatus_OBJS
,append_dsn=statusobjs
,PK=LIBREF MEMNAME OBJNAME OBJTYPE
,etlsource=&sysmacroname
,loadtype=TXTEMPORAL
,tech_from=TX_FROM
,tech_to=TX_TO
%if &cat = #ALL %then %do;
,close_vars=LIBREF MEMNAME
%end;
,dclib=&mpelib
)
%put load mpe_datastatus_cats;
proc sql;
create table statuscats as
select libref,
memname,
count(*) as nobjs,
min(created) as created,
max(modified) as modified
from catdata
group by 1,2;
%bitemporal_dataloader(base_lib=&mpelib
,base_dsn=mpe_datastatus_cats
,append_dsn=statuscats
,PK=LIBREF MEMNAME
,etlsource=&sysmacroname
,loadtype=TXTEMPORAL
,tech_from=TX_FROM
,tech_to=TX_TO
%if &cat = #ALL %then %do;
,close_vars=LIBREF
%end;
,dclib=&mpelib
)
%mend mpe_refreshcatalogs;

View File

@ -0,0 +1,38 @@
/**
@file
@brief Testing mpe_refreshcatalogs macro
<h4> SAS Macros </h4>
@li mpe_refreshcatalogs.sas
@li mp_assert.sas
@li mp_assertscope.sas
@li mp_ds2md.sas
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
and may not be re-distributed or re-sold without the express permission of
4GL Apps Ltd.
**/
%mp_assertscope(SNAPSHOT)
%mpe_refreshcatalogs(FMTONLY)
%mp_assertscope(COMPARE,
desc=Checking macro variables against previous snapshot
)
/* make sure that the process picks up the catalog */
proc sql noprint;
create table work.test1 as
select *
from &mpelib..mpe_datacatalog_cats(where=(&dc_dttmtfmt. lt tx_to))
where libref="FMTONLY";
%let test1=0;
select count(*) into: test1 from work.test1;
%mp_assert(
iftrue=(&test1>0),
desc=Checking fmtonly.dcfmts was picked up
)
%mp_ds2md(work.test1)

View File

@ -48,11 +48,6 @@ create table cols as
,msg=%str(syscc=&syscc afer &lib cols extraction) ,msg=%str(syscc=&syscc afer &lib cols extraction)
) )
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(syscc=&syscc afer &lib indexes extraction)
)
%if &engine=SQLSVR %then %do; %if &engine=SQLSVR %then %do;
proc sql; proc sql;
connect using &lib; connect using &lib;
@ -175,6 +170,11 @@ create table cols as
%end; %end;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(syscc=&syscc afer &lib indexes extraction)
)
/* load columns */ /* load columns */
%bitemporal_dataloader(base_lib=&mpelib %bitemporal_dataloader(base_lib=&mpelib
,base_dsn=mpe_datacatalog_vars ,base_dsn=mpe_datacatalog_vars
@ -295,7 +295,7 @@ proc sql;
%if &ds ne #ALL %then %do; %if &ds ne #ALL %then %do;
and upcase(memname)="&ds" and upcase(memname)="&ds"
%end; %end;
; ;
%end; %end;
%bitemporal_dataloader(base_lib=&mpelib %bitemporal_dataloader(base_lib=&mpelib
@ -314,12 +314,32 @@ proc sql;
%if &ds = #ALL %then %do; %if &ds = #ALL %then %do;
proc sql; proc sql;
create table statuslibs as select create table work.sumcat as
select libname as libref,
count(distinct memname) as catalog_cnt
from dictionary.catalogs
where upcase(libname)="&lib"
group by 1;
create table work.sumdsn as select
libref libref
,sum(filesize) as libsize ,sum(filesize) as libsize
,count(*) as table_cnt ,count(*) as table_cnt
from statustabs from statustabs
group by 1; group by 1;
create table work.libs as
select libref from work.sumcat
union
select libref from work.sumdsn;
create table work.statuslibs as
select a.libref,
b.libsize,
b.table_cnt,
c.catalog_cnt
from work.libs a
left join work.sumdsn b
on a.libref=b.libref
left join work.sumcat c
on a.libref=c.libref;
%bitemporal_dataloader(base_lib=&mpelib %bitemporal_dataloader(base_lib=&mpelib
,base_dsn=mpe_datastatus_libs ,base_dsn=mpe_datastatus_libs

View File

@ -0,0 +1,50 @@
/**
@file
@brief Testing mpe_refreshtables macro
<h4> SAS Macros </h4>
@li mpe_refreshtables.sas
@li mp_assert.sas
@li mp_assertscope.sas
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
and may not be re-distributed or re-sold without the express permission of
4GL Apps Ltd.
**/
%mp_assertscope(SNAPSHOT)
%mpe_refreshtables(FMTONLY)
%mp_assertscope(COMPARE,
desc=Checking macro variables against previous snapshot
)
/* make sure that the process picks up a library that contains only a single
catalog */
proc sql;
create table work.libinfo as
select a.engine,
a.libname,
a.paths,
a.perms,
a.owners,
a.schemas,
a.libid,
b.libsize,
b.table_cnt,
b.catalog_cnt
from &mpelib..mpe_datacatalog_libs(where=(&dc_dttmtfmt. lt tx_to)) a
left join &mpelib..mpe_datastatus_libs(where=(&dc_dttmtfmt. lt tx_to)) b
on a.libref=b.libref
where a.libref="&libref";
%let test1=0;
data _null_;
set work.libinfo;
call symputx('test1',table_cnt);
run;
%mp_assert(
iftrue=(&test1>0),
desc=Checking fmtonly.dcfmts was picked up
)

View File

@ -94,50 +94,18 @@
}, },
{ {
"name": "viya", "name": "viya",
"serverUrl": "https://sas.4gl.io", "serverUrl": "https://viya-f0g8ht62vq.engage.sas.com",
"serverType": "SASVIYA", "serverType": "SASVIYA",
"httpsAgentOptions": { "httpsAgentOptions": {
"allowInsecureRequests": false "allowInsecureRequests": false
}, },
"appLoc": "/Public/app/dcplaceholder", "appLoc": "/Public/app/dcplaceholder",
"macroFolders": [
"sasjs/targets/viya/macros_viya"
],
"programFolders": [
"sasjs/db/datactrl"
],
"binaryFolders": [],
"buildConfig": {
"initProgram": "sasjs/utils/buildinitviya.sas",
"buildResultsFolder": "sasjsresults",
"buildOutputFolder": "sasjsbuild",
"buildOutputFileName": "viya.sas"
},
"serviceConfig": {
"initProgram": "sasjs/utils/serviceinitviya.sas",
"serviceFolders": [
"sasjs/targets/viya/services_viya/viya_users",
"sasjs/targets/viya/services_viya/admin",
"sasjs/targets/viya/services_viya/public"
]
},
"deployConfig": { "deployConfig": {
"deployServicePack": true, "deployServicePack": true,
"deployScripts": [ "deployScripts": [
"sasjs/utils/viyadeploy.sh" "sasjs/utils/viyadeploy.sh"
] ]
}, },
"contextName": "SAS Job Execution compute context"
},
{
"name": "viyacloud",
"serverUrl": "https://4gl.viyacloud.sas.com",
"serverType": "SASVIYA",
"httpsAgentOptions": {
"rejectUnauthorized": false,
"allowInsecureRequests": true
},
"appLoc": "/30.SASApps/app/dc",
"macroFolders": [ "macroFolders": [
"sasjs/targets/viya/macros_viya" "sasjs/targets/viya/macros_viya"
], ],
@ -146,36 +114,31 @@
], ],
"buildConfig": { "buildConfig": {
"initProgram": "sasjs/utils/buildinitviya.sas", "initProgram": "sasjs/utils/buildinitviya.sas",
"termProgram": "sasjs/utils/buildtermviya.sas",
"macroVars": {
"dcpath": "/opt/sas/viya/config/var/tmp/dc",
"adminGroup": "DataBuilders"
},
"buildResultsFolder": "sasjsresults", "buildResultsFolder": "sasjsresults",
"buildOutputFolder": "sasjsbuild", "buildOutputFolder": "sasjsbuild",
"buildOutputFileName": "viya.sas" "buildOutputFileName": "viya.sas",
"termProgram": "",
"macroVars": {}
}, },
"serviceConfig": { "serviceConfig": {
"initProgram": "sasjs/utils/serviceinitviya.sas",
"serviceFolders": [ "serviceFolders": [
"sasjs/targets/viya/services_viya/viya_users", "sasjs/targets/viya/services_viya/viya_users",
"sasjs/targets/viya/services_viya/admin", "sasjs/targets/viya/services_viya/admin",
"sasjs/targets/viya/services_viya/public" "sasjs/targets/viya/services_viya/public"
], ],
"initProgram": "sasjs/utils/serviceinitviya.sas",
"termProgram": "", "termProgram": "",
"macroVars": {} "macroVars": {}
}, },
"streamConfig": { "streamConfig": {
"streamWeb": true, "streamWeb": true,
"streamWebFolder": "webv", "streamWebFolder": "web",
"webSourcePath": "../client/dist", "webSourcePath": "../client/dist",
"streamServiceName": "clickme", "streamServiceName": "DC",
"streamLogo": "favicon.ico",
"assetPaths": [] "assetPaths": []
}, },
"deployConfig": { "contextName": "SAS Job Execution compute context"
"deployServicePack": true
},
"contextName": "Datacontroller compute context"
}, },
{ {
"name": "vtest", "name": "vtest",

View File

@ -675,7 +675,7 @@ data xl_rules;
keep xl_column xl_rule; keep xl_column xl_rule;
run; run;
%mpe_dsmeta(&libds, outds=dsmeta) %mpe_dsmeta(&orig_libds, outds=dsmeta)
%mpe_getversions(&mpelib, %mpe_getversions(&mpelib,
%scan(&orig_libds,1,.), %scan(&orig_libds,1,.),

View File

@ -54,7 +54,10 @@ data _null_;
/* if a TXTEMPORAL table then filter as such */ /* if a TXTEMPORAL table then filter as such */
call symputx('txfrom',var_txfrom); call symputx('txfrom',var_txfrom);
call symputx('txto',var_txto); call symputx('txto',var_txto);
run;
/* if a format, extract relevant info */
data _null_;
ds=symget('ds'); ds=symget('ds');
is_fmt=0; is_fmt=0;
if subpad(cats(reverse(ds)),1,3)=:'CF-' then do; if subpad(cats(reverse(ds)),1,3)=:'CF-' then do;

View File

@ -76,3 +76,37 @@ run;
test=EQUALS 3, test=EQUALS 3,
outds=work.test_results outds=work.test_results
) )
/* test 3 - when there is a format catalog / nothing else in the library */
data work.params3;
length name $32 value $1000;
name='type';value='SAS';output;
name='table';value="FMTONLY.DCFMTS-FC";output;
name='filter';value='0';output;
run;
%mx_testservice(&_program,
viyacontext=&defaultcontext,
inputparams=work.params3,
outref=web3,
viyaresult=WEBOUT_TXT
)
data work.results3;
infile web3;
input;
putlog _infile_;
if _infile_=:'datalines4;' then do;
output;
output;
output;
stop;
end;
if _n_>100 then stop;
run;
%mp_assertdsobs(work.results3,
desc=datalines file is successfully returned for LONE format catalog,
test=EQUALS 3,
outds=work.test_results
)

View File

@ -1,85 +1,86 @@
/** /**
@file refreshlibinfo.sas @file refreshlibinfo.sas
@brief Refresh the Data Catalog for a particular library @brief Refresh the Data Catalog for a particular library
@details When showing library info in the VIEW menu, the data is taken from @details When showing library info in the VIEW menu, the data is taken from
the Data Catalog tables. These may be empty or outdated, and so this service the Data Catalog tables. These may be empty or outdated, and so this service
allows end users to run a refresh of the data. allows end users to run a refresh of the data.
<h4> Service Inputs </h4> <h4> Service Inputs </h4>
<h5> lib2refresh </h5> <h5> lib2refresh </h5>
Should contain the libref to be refreshed. Should contain the libref to be refreshed.
|libref:$8.| |libref:$8.|
|---| |---|
|SOMELIB| |SOMELIB|
<h4> Service Outputs </h4> <h4> Service Outputs </h4>
<h5> libinfo </h5> <h5> libinfo </h5>
|engine $|libname $|paths $|perms $|owners $|schemas $ |libid $|libsize $|table_cnt | |engine $|libname $|paths $|perms $|owners $|schemas $ |libid $|libsize $|table_cnt |
|---|---|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|---|---|
|V9|SOMELIB|"some/path"|rwxrwxr-x|sassrv|` `|` `|636MB|33| |V9|SOMELIB|"some/path"|rwxrwxr-x|sassrv|` `|` `|636MB|33|
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li dc_assignlib.sas @li dc_assignlib.sas
@li dc_refreshcatalog.sas @li dc_refreshcatalog.sas
@li mp_abort.sas @li mp_abort.sas
@version 9.3 @version 9.3
@author 4GL Apps Ltd @author 4GL Apps Ltd
@copyright 4GL Apps Ltd. This code may only be used within Data Controller @copyright 4GL Apps Ltd. This code may only be used within Data Controller
and may not be re-distributed or re-sold without the express permission of and may not be re-distributed or re-sold without the express permission of
4GL Apps Ltd. 4GL Apps Ltd.
**/ **/
%mpeinit() %mpeinit()
%webout(FETCH) %webout(FETCH)
%mp_abort(iftrue= (&syscc ne 0) %mp_abort(iftrue= (&syscc ne 0)
,msg=%str(syscc=&syscc Problem on startup) ,msg=%str(syscc=&syscc Problem on startup)
) )
%let libref=; %let libref=;
data _null_; data _null_;
set work.lib2refresh; set work.lib2refresh;
call symputx('libref',libref); call symputx('libref',libref);
run; run;
%mp_abort(iftrue= (&syscc ne 0) %mp_abort(iftrue= (&syscc ne 0)
,msg=%str(syscc=&syscc Problem with inputs - was lib2refresh object sent?) ,msg=%str(syscc=&syscc Problem with inputs - was lib2refresh object sent?)
) )
%dc_assignlib(WRITE,&libref) %dc_assignlib(WRITE,&libref)
%mp_abort(iftrue= (&syscc ne 0) %mp_abort(iftrue= (&syscc ne 0)
,msg=%str(syscc=&syscc after lib assignment) ,msg=%str(syscc=&syscc after lib assignment)
) )
%dc_refreshcatalog(&libref) %dc_refreshcatalog(&libref)
%mp_abort(iftrue= (&syscc ne 0) %mp_abort(iftrue= (&syscc ne 0)
,msg=%str(syscc=&syscc Problem when running the catalog refresh) ,msg=%str(syscc=&syscc Problem when running the catalog refresh)
) )
/* get libinfo */ /* get libinfo */
proc sql; proc sql;
create table work.libinfo as create table work.libinfo as
select a.engine, select a.engine,
a.libname, a.libname,
a.paths, a.paths,
a.perms, a.perms,
a.owners, a.owners,
a.schemas, a.schemas,
a.libid, a.libid,
b.libsize, b.libsize,
b.table_cnt b.table_cnt,
from &mpelib..mpe_datacatalog_libs(where=(&dc_dttmtfmt. lt tx_to)) a b.catalog_cnt
inner join &mpelib..mpe_datastatus_libs(where=(&dc_dttmtfmt. lt tx_to)) b from &mpelib..mpe_datacatalog_libs(where=(&dc_dttmtfmt. lt tx_to)) a
on a.libref=b.libref inner join &mpelib..mpe_datastatus_libs(where=(&dc_dttmtfmt. lt tx_to)) b
where a.libref="&libref"; on a.libref=b.libref
where a.libref="&libref";
%webout(OPEN)
%webout(OBJ,libinfo) %webout(OPEN)
%webout(CLOSE) %webout(OBJ,libinfo)
%webout(CLOSE)

View File

@ -355,7 +355,7 @@ run;
%mp_getcols(&libds, outds=cols) %mp_getcols(&libds, outds=cols)
%mpe_dsmeta(&libds, outds=dsmeta) %mpe_dsmeta(&orig_libds, outds=dsmeta)
%mpe_getversions(&mpelib, %mpe_getversions(&mpelib,
%scan(&orig_libds,1,.), %scan(&orig_libds,1,.),

View File

@ -167,7 +167,8 @@ create table work.libinfo as
a.schemas, a.schemas,
a.libid, a.libid,
coalesce(b.libsize,0) as libsize, coalesce(b.libsize,0) as libsize,
coalesce(b.table_cnt,0) as table_cnt coalesce(b.table_cnt,0) as table_cnt,
coalesce(b.catalog_cnt,0) as catalog_cnt
from &mpelib..mpe_datacatalog_libs(where=(&dc_dttmtfmt. lt tx_to)) a from &mpelib..mpe_datacatalog_libs(where=(&dc_dttmtfmt. lt tx_to)) a
left join &mpelib..mpe_datastatus_libs(where=(&dc_dttmtfmt. lt tx_to)) b left join &mpelib..mpe_datastatus_libs(where=(&dc_dttmtfmt. lt tx_to)) b
on a.libref=b.libref on a.libref=b.libref

View File

@ -9,6 +9,7 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mpe_refreshlibs.sas @li mpe_refreshlibs.sas
@li dc_assignlib.sas @li dc_assignlib.sas
@li mpe_refreshcatalogs.sas
@li mpe_refreshtables.sas @li mpe_refreshtables.sas
@li mm_getrepos.sas @li mm_getrepos.sas
@ -44,6 +45,7 @@ run;
%dc_assignlib(WRITE,&libref) /* write just in order to assign direct lib */ %dc_assignlib(WRITE,&libref) /* write just in order to assign direct lib */
%mpe_refreshlibs(lib=&libref) %mpe_refreshlibs(lib=&libref)
%mpe_refreshtables(&libref) %mpe_refreshtables(&libref)
%mpe_refreshcatalogs(&libref)
%end; %end;
%else %do xx=1 %to &repocnt; %else %do xx=1 %to &repocnt;
options metarepository=&&repo&xx; options metarepository=&&repo&xx;
@ -73,6 +75,7 @@ run;
%do i=1 %to &libcnt; %do i=1 %to &libcnt;
%dc_assignlib(WRITE,&&lib&i) %dc_assignlib(WRITE,&&lib&i)
%mpe_refreshtables(&&lib&i) %mpe_refreshtables(&&lib&i)
%mpe_refreshcatalogs(&&lib&i)
%end; %end;
%end; %end;

View File

@ -9,6 +9,7 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mpe_refreshlibs.sas @li mpe_refreshlibs.sas
@li dc_assignlib.sas @li dc_assignlib.sas
@li mpe_refreshcatalogs.sas
@li mpe_refreshtables.sas @li mpe_refreshtables.sas
@ -34,6 +35,8 @@ data libraries;
str=cats('%mpe_refreshtables(',libref,')'); str=cats('%mpe_refreshtables(',libref,')');
put str; put str;
putlog str; putlog str;
str=cats('%mpe_refreshcatalogs(',libref,')');
put str;
run; run;
%inc executor/source2; %inc executor/source2;

View File

@ -10,6 +10,7 @@
@li mpe_refreshlibs.sas @li mpe_refreshlibs.sas
@li dc_assignlib.sas @li dc_assignlib.sas
@li mpe_refreshtables.sas @li mpe_refreshtables.sas
@li mpe_refreshcatalogs.sas
@version 3.4 @version 3.4
@ -19,19 +20,29 @@
4GL Apps Ltd. 4GL Apps Ltd.
**/ **/
%macro dc_refreshcatalog(); %macro dc_refreshcatalog(libref);
%mpe_refreshlibs() %if #&libref# ne ## %then %do;
%put &sysmacroname: assigning specific libref, &libref;
filename executor catalog 'work.code.code.source'; %dc_assignlib(WRITE,&libref) /* write just in order to assign direct lib */
data libraries; %mpe_refreshlibs(lib=&libref)
set &mpelib..mpe_datacatalog_libs; %mpe_refreshtables(&libref)
where &dc_dttmtfmt. le TX_TO; %mpe_refreshcatalogs(&libref)
file executor; %end;
str=cats('%mpe_refreshtables(',libref,')'); %else %do;
put str; %mpe_refreshlibs()
putlog str; filename executor catalog 'work.code.code.source';
run; data libraries;
%inc executor; set &mpelib..mpe_datacatalog_libs;
where &dc_dttmtfmt. le TX_TO;
file executor;
str=cats('%mpe_refreshtables(',libref,')');
put str;
str=cats('%mpe_refreshcatalogs(',libref,')');
put str;
putlog str;
run;
%inc executor;
%end;
%mend dc_refreshcatalog; %mend dc_refreshcatalog;

View File

@ -7,6 +7,7 @@
@li mf_getapploc.sas @li mf_getapploc.sas
@li mf_mkdir.sas @li mf_mkdir.sas
@li mf_trimstr.sas @li mf_trimstr.sas
@li mp_abort.sas
@li mpe_getvars.sas @li mpe_getvars.sas
@li mpe_makedata.sas @li mpe_makedata.sas
@li mpe_makedatamodel.sas @li mpe_makedatamodel.sas
@ -50,9 +51,33 @@ options noquotelenmax;
%put &=admin; %put &=admin;
%mf_mkdir(&dcpath) %mf_mkdir(&dcpath)
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(Unable to create &dcpath using &sysuserid)
)
%mf_mkdir(&dcpath/secret) %mf_mkdir(&dcpath/secret)
%mf_mkdir(&dcpath/dc_staging) %mf_mkdir(&dcpath/dc_staging)
/* check we have physical permissions to the DCLIB folder */
data _null_;
putlog "dcpath=&dcpath/permTest.txt";
putlog "sysuserid=&sysuserid";
data _null_;
file "&dcpath/permTest.txt";
run;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(User &sysuserid does not have WRITE permissions to: &dcpath )
)
filename delfile "&dcpath/permTest.txt";
data _null_;
rc=fdelete('delfile');
run;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program..sas
,msg=%str(User &sysuserid could create (but not delete) &dcpath/permTest.txt )
)
libname &dclib "&dcpath"; libname &dclib "&dcpath";
%global admin; %global admin;
@ -60,11 +85,23 @@ libname &dclib "&dcpath";
%mpe_makedatamodel(lib=&dclib) %mpe_makedatamodel(lib=&dclib)
%mpe_makedata(lib=&dclib,mpeadmins=&admin,path=%str(&dcpath)) %mpe_makedata(lib=&dclib,mpeadmins=&admin,path=%str(&dcpath))
%mp_abort(iftrue=(&syscc ne 0)
,mac=&sysmacroname
,msg=%str(Err during &dclib build)
)
/* sample data library */ /* sample data library */
%mf_mkdir(&dcpath/dc_demo) %mf_mkdir(&dcpath/dc_demo)
libname dcdemo "&dcpath/dc_demo"; libname dcdemo "&dcpath/dc_demo";
%mpe_makesampledata(outlib=DCDEMO) %mpe_makesampledata(outlib=DCDEMO)
%mp_abort(iftrue=(&syscc ne 0)
,mac=&sysmacroname
,msg=%str(Err during demo data build)
)
/* the DC precode is stored in the root of the project */ /* the DC precode is stored in the root of the project */
%let root=%mf_getapploc(&_program)/services; %let root=%mf_getapploc(&_program)/services;
%put &=root; %put &=root;
@ -167,7 +204,7 @@ run;
*/ */
%mp_abort(iftrue=(&syscc ne 0) %mp_abort(iftrue=(&syscc ne 0)
,mac=&sysmacroname ,mac=&sysmacroname
,msg=%str(Err during DB build) ,msg=%str(Err during settings job creation)
) )

View File

@ -21,7 +21,7 @@ REMOVE THAT LAST MACRO
%let syscc=0; %let syscc=0;
%global apploc _program dclib defaultcontext _debug sasjs_mdebug dc_dttmtfmt; %global apploc _program dclib defaultcontext _debug sasjs_mdebug dc_dttmtfmt;
%let defaultcontext=Datacontroller compute context; %let defaultcontext=SAS Job Execution compute context;
%let sasjs_mdebug=0; %let sasjs_mdebug=0;
options mprint mprintnest nobomfile lrecl=32767; options mprint mprintnest nobomfile lrecl=32767;

View File

@ -28,7 +28,7 @@
%global apploc _program; %global apploc _program;
%let defaultcontext=Datacontroller compute context; %let defaultcontext=SAS Job Execution compute context;
data _null_; data _null_;
length _pgm $1000; length _pgm $1000;
@ -60,6 +60,9 @@ run;
%let testloc=%sysfunc(pathname(&DC_LIBREF))/fmt%mf_getuniquefileref(); %let testloc=%sysfunc(pathname(&DC_LIBREF))/fmt%mf_getuniquefileref();
%mf_mkdir(&testloc) %mf_mkdir(&testloc)
libname dctest "&testloc"; libname dctest "&testloc";
/* test library with only one format catalog */
%mf_mkdir(&testloc/fmtonly)
libname fmtonly "&testloc/fmtonly";
/* add formats */ /* add formats */
PROC FORMAT library=dctest.dcfmts; PROC FORMAT library=dctest.dcfmts;
@ -99,6 +102,10 @@ run;
proc append base=&dc_libref..mpe_tables data=work.append; proc append base=&dc_libref..mpe_tables data=work.append;
run; run;
/* lone format catalog */
proc format cntlin=work.fmts library=fmtonly.dcfmts;
run;
/* add some other tables */ /* add some other tables */
%mp_coretable(LOCKTABLE,libds=dctest.locktable) %mp_coretable(LOCKTABLE,libds=dctest.locktable)
%mp_coretable(DIFFTABLE,libds=dctest.difftable) %mp_coretable(DIFFTABLE,libds=dctest.difftable)
@ -130,6 +137,7 @@ options mprint;
put _infile_; put _infile_;
if last then do; if last then do;
put "libname dctest '&testloc';"; put "libname dctest '&testloc';";
put "libname fmtonly '&testloc/fmtonly';";
end; end;
run; run;
data _null_; data _null_;
@ -151,6 +159,7 @@ options mprint;
put _infile_; put _infile_;
if last then do; if last then do;
put "libname dctest '&testloc';"; put "libname dctest '&testloc';";
put "libname fmtonly '&testloc/fmtonly';";
end; end;
run; run;
%ms_deletefile(&root/services/public/settings.sas) %ms_deletefile(&root/services/public/settings.sas)
@ -182,6 +191,7 @@ options mprint;
put _infile_; put _infile_;
if last then do; if last then do;
put "libname dctest '&testloc';"; put "libname dctest '&testloc';";
put "libname fmtonly '&testloc/fmtonly';";
end; end;
run; run;
%mm_deletestp(target=&root/services/public/Data_Controller_Settings) %mm_deletestp(target=&root/services/public/Data_Controller_Settings)

View File

@ -2,6 +2,11 @@
@file buildinitviya.sas @file buildinitviya.sas
@brief initialisation for viya build program @brief initialisation for viya build program
<h4> SAS Macros </h4>
@li mfv_getfolderpath.sas
@li mfv_getpathuri.sas
@li mv_createfolder.sas
**/ **/
options nonotes nomprint; options nonotes nomprint;
@ -9,4 +14,8 @@ options nonotes nomprint;
/* update apploc to default to user home area if not set */ /* update apploc to default to user home area if not set */
%let apploc=%sysfunc(ifc("&apploc"="/Public/app/dcplaceholder" %let apploc=%sysfunc(ifc("&apploc"="/Public/app/dcplaceholder"
,/Users/&sysuserid/My Folder/Data Controller ,/Users/&sysuserid/My Folder/Data Controller
,&apploc)); ,&apploc));
/* ensure the correct casing of appLoc */
%mv_createfolder(path=&apploc)
%let apploc=%mfv_getfolderpath(%mfv_getpathuri(&apploc));