1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-29 13:40:06 +00:00

Compare commits

...

16 Commits

Author SHA1 Message Date
Allan Bowe
4b69e91362 Merge pull request #84 from sasjs/issue83
fix: refactored mp_getconstraints due to apparent bug in dictionary.table_constraints
2021-10-01 13:56:57 +01:00
Allan Bowe
8f9715035a chore: removing gitpod badge and switching Node to LTS 2021-10-01 12:55:54 +00:00
Allan Bowe
35ddccaa16 fix: refactored mp_getconstraints due to apparent bug in dictionary.table_constraints. Added test. Closes #83 2021-10-01 13:04:26 +01:00
Allan Bowe
cb0ddfb61c fix: applying tag wrappers to sasjsAbort response json. The adapter will always extract from these in any case, and it seems there are some situations where it is not possible to avoid errors being thrown in SAS 9 (resulting in a log always appearing in the response). This change will make it much easier to handle on the frontend side. 2021-09-30 18:50:02 +01:00
Allan Bowe
c3b6f06b3a chore: merge commit 2021-09-30 14:48:26 +01:00
Allan Bowe
8046d5a0b1 fix: updating CLI dependency to avoid npm install warnings 2021-09-30 14:47:56 +01:00
Allan Bowe
aed07f2943 Merge pull request #82 from sasjs/checkmsg
fix: adding sysmsg() to failed metadata calls
2021-09-30 14:44:36 +01:00
Allan Bowe
5bf87a78b8 fix: adding sysmsg() to failed metadata calls 2021-09-30 14:32:52 +01:00
Allan Bowe
0851523d18 chore: gitpod settings 2021-09-29 11:28:59 +00:00
Allan Bowe
9e2de81dae Merge pull request #81 from sasjs/issue80
fix: removing nonprintables from cards data.  Closes #80
2021-09-27 22:42:36 +03:00
Allan Bowe
4887f355c8 fix: removing redundant dlm option 2021-09-27 20:14:52 +01:00
Allan Bowe
9b32e6e3f2 fix: removing nonprintables from cards data. Closes #80 2021-09-27 20:12:48 +01:00
Allan Bowe
74790ec80e fix: adding trim to avoid converting trailing blanks 2021-09-27 17:46:53 +01:00
Allan Bowe
afd8a754b4 Merge pull request #79 from sasjs/issue78
feat: adding binary variable support to mp_ds2cards.sas
2021-09-27 18:57:16 +03:00
Allan Bowe
bc1f7b3baa fix: updating test result and making mp_ds2cards header doxygen compliant 2021-09-27 16:39:28 +01:00
Allan Bowe
51690e68dc feat: adding binary variable support to mp_ds2cards.sas, updating documentation, and including two tests. Closes #78 2021-09-27 16:15:25 +01:00
14 changed files with 1453 additions and 120 deletions

View File

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

101
all.sas
View File

@@ -975,7 +975,8 @@ https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md#functionex
%end;
%end;
%else %do;
%put dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
@@ -1037,7 +1038,11 @@ https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md#functionex
%let vlen = %str( );
%end;
%end;
%else %put dataset &libds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));
@@ -1161,7 +1166,11 @@ returns:
%let vnum = %str( );
%end;
%end;
%else %put dataset &ds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));
@@ -1210,7 +1219,11 @@ Usage:
%let vtype = %str( );
%end;
%end;
%else %put dataset &libds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));
@@ -1817,7 +1830,7 @@ Usage:
msg=cats('"',msg,'"');
if symexist('_debug') then debug=quote(trim(symget('_debug')));
else debug='""';
if debug ge '"131"' then put '>>weboutBEGIN<<';
put '>>weboutBEGIN<<';
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
put ',"sasjsAbort" : [{';
put ' "MSG":' msg ;
@@ -1849,7 +1862,7 @@ Usage:
put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
put "}" @;
if debug ge '"131"' then put '>>weboutEND<<';
put '>>weboutEND<<';
run;
%put _all_;
@@ -3315,12 +3328,21 @@ run;
@file
@brief Create a CARDS file from a SAS dataset.
@details Uses dataset attributes to convert all data into datalines.
Running the generated file will rebuild the original dataset.
Running the generated file will rebuild the original dataset. Includes
support for large decimals, binary data, PROCESSED_DTTM columns, and
alternative encoding. If the input dataset is empty, the cards file will
still be created.
Additional support to generate a random sample and max rows.
Usage:
%mp_ds2cards(base_ds=sashelp.class
, tgt_ds=work.class
, cards_file= "C:\temp\class.sas"
, maxobs=5)
, showlog=NO
, maxobs=5
)
TODO:
- labelling the dataset
@@ -3331,15 +3353,24 @@ run;
that is converted to a cards file.
@param [in] tgt_ds= Table that the generated cards file would create.
Optional - if omitted, will be same as BASE_DS.
@param [out] cards_file= Location in which to write the (.sas) cards file
@param [in] maxobs= to limit output to the first <code>maxobs</code>
observations
@param [in] showlog= whether to show generated cards file in the SAS log
(YES/NO)
@param [in] outencoding= provide encoding value for file statement (eg utf-8)
@param [in] append= If NO then will rebuild the cards file if it already
@param [out] cards_file= ("%sysfunc(pathname(work))/cardgen.sas") Location in
which to write the (.sas) cards file
@param [in] maxobs= (max) To limit output to the first <code>maxobs</code>
observations, enter an integer here.
@param [in] random_sample= (NO) Set to YES to generate a random sample of
data. Can be quite slow.
@param [in] showlog= (YES) Whether to show generated cards file in the SAS
log. Valid values:
@li YES
@li NO
@param [in] outencoding= Provide encoding value for file statement (eg utf-8)
@param [in] append= (NO) If NO then will rebuild the cards file if it already
exists, otherwise will append to it. Used by the mp_lib2cards.sas macro.
<h4> Related Macros </h4>
@li mp_lib2cards.sas
@li mp_ds2inserts.sas
@li mp_mdtablewrite.sas
@version 9.2
@author Allan Bowe
@@ -3364,7 +3395,7 @@ run;
%if (&tgt_ds = ) %then %let tgt_ds=&base_ds;
%if %index(&tgt_ds,.)=0 %then %let tgt_ds=WORK.%scan(&base_ds,2,.);
%if ("&outencoding" ne "") %then %let outencoding=encoding="&outencoding";
%if ("&append" = "") %then %let append=;
%if ("&append" = "" or "&append" = "NO") %then %let append=;
%else %let append=mod;
/* get varcount */
@@ -3450,7 +3481,18 @@ data datalines_2;
,put(',name,',best32.-l)
,substrn(put(',name,',bestd32.-l),1
,findc(put(',name,',bestd32.-l),"0","TBK")))');
else dataline=name;
/**
* binary data must be converted, to store in text format. It is identified
* by the presence of the $HEX keyword in the format.
*/
else if upcase(format)=:'$HEX' then
dataline=cats('put(trim(',name,'),',format,')');
/**
* There is no easy way to store line breaks in a cards file.
* To discuss this, use: https://github.com/sasjs/core/issues/80
* Removing all nonprintables with kw (keep writeable)
*/
else dataline=cats('compress(',name,', ,"kw")');
run;
proc sql noprint;
@@ -3475,7 +3517,8 @@ data _null_;
/* Build input statement */
if type='char' then type3=':$char.';
if upcase(format)=:'$HEX' then type3=':'!!format;
else if type='char' then type3=':$char.';
str2=put(name,$33.)||type3;
@@ -3497,11 +3540,12 @@ data _null_;
file &cards_file. &outencoding lrecl=32767 termstr=nl &append;
length __attrib $32767;
if _n_=1 then do;
put '/*******************************************************************';
put " Datalines for %upcase(%scan(&base_ds,2)) dataset ";
put " Generated by %nrstr(%%)mp_ds2cards()";
put " Available on github.com/sasjs/core";
put '********************************************************************/';
put '/**';
put ' @file';
put " @brief Datalines for %upcase(%scan(&base_ds,2)) dataset";
put " @details Generated by %nrstr(%%)mp_ds2cards()";
put " Available on github.com/sasjs/core";
put '**/';
put "data &tgt_ds &indexes;";
put "attrib ";
%do i = 1 %to &nvars;
@@ -3525,11 +3569,11 @@ data _null_;
put 'run;';
end;
else do;
put "infile cards dsd delimiter=',';";
put "infile cards dsd;";
put "input ";
%do i = 1 %to &nvars.;
%if(%length(&&input_stmt_&i..)) %then
put " &&input_stmt_&i..";
put " &&input_stmt_&i..";
;
%end;
put ";";
@@ -4422,8 +4466,11 @@ create table &outds as
on upcase(a.TABLE_CATALOG)=upcase(b.TABLE_CATALOG)
and upcase(a.TABLE_NAME)=upcase(b.TABLE_NAME)
and a.constraint_name=b.constraint_name
where upcase(a.TABLE_CATALOG)="&lib"
and upcase(b.TABLE_CATALOG)="&lib"
/**
* We cannot apply this clause to the underlying dictionary table. See:
* https://communities.sas.com/t5/SAS-Programming/Unexpected-Where-Clause-behaviour-in-dictionary-TABLE/m-p/771554#M244867
*/
where calculated libref="&lib"
%if "&ds" ne "" %then %do;
and upcase(a.TABLE_NAME)="&ds"
and upcase(b.TABLE_NAME)="&ds"

View File

@@ -51,7 +51,8 @@
%end;
%end;
%else %do;
%put dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;

View File

@@ -43,7 +43,11 @@
%let vlen = %str( );
%end;
%end;
%else %put dataset &libds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));

View File

@@ -43,7 +43,11 @@ returns:
%let vnum = %str( );
%end;
%end;
%else %put dataset &ds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));

View File

@@ -39,7 +39,11 @@ Usage:
%let vtype = %str( );
%end;
%end;
%else %put dataset &libds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));

View File

@@ -169,7 +169,7 @@
msg=cats('"',msg,'"');
if symexist('_debug') then debug=quote(trim(symget('_debug')));
else debug='""';
if debug ge '"131"' then put '>>weboutBEGIN<<';
put '>>weboutBEGIN<<';
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
put ',"sasjsAbort" : [{';
put ' "MSG":' msg ;
@@ -201,7 +201,7 @@
put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
put "}" @;
if debug ge '"131"' then put '>>weboutEND<<';
put '>>weboutEND<<';
run;
%put _all_;

View File

@@ -2,12 +2,21 @@
@file
@brief Create a CARDS file from a SAS dataset.
@details Uses dataset attributes to convert all data into datalines.
Running the generated file will rebuild the original dataset.
Running the generated file will rebuild the original dataset. Includes
support for large decimals, binary data, PROCESSED_DTTM columns, and
alternative encoding. If the input dataset is empty, the cards file will
still be created.
Additional support to generate a random sample and max rows.
Usage:
%mp_ds2cards(base_ds=sashelp.class
, tgt_ds=work.class
, cards_file= "C:\temp\class.sas"
, maxobs=5)
, showlog=NO
, maxobs=5
)
TODO:
- labelling the dataset
@@ -18,15 +27,24 @@
that is converted to a cards file.
@param [in] tgt_ds= Table that the generated cards file would create.
Optional - if omitted, will be same as BASE_DS.
@param [out] cards_file= Location in which to write the (.sas) cards file
@param [in] maxobs= to limit output to the first <code>maxobs</code>
observations
@param [in] showlog= whether to show generated cards file in the SAS log
(YES/NO)
@param [in] outencoding= provide encoding value for file statement (eg utf-8)
@param [in] append= If NO then will rebuild the cards file if it already
@param [out] cards_file= ("%sysfunc(pathname(work))/cardgen.sas") Location in
which to write the (.sas) cards file
@param [in] maxobs= (max) To limit output to the first <code>maxobs</code>
observations, enter an integer here.
@param [in] random_sample= (NO) Set to YES to generate a random sample of
data. Can be quite slow.
@param [in] showlog= (YES) Whether to show generated cards file in the SAS
log. Valid values:
@li YES
@li NO
@param [in] outencoding= Provide encoding value for file statement (eg utf-8)
@param [in] append= (NO) If NO then will rebuild the cards file if it already
exists, otherwise will append to it. Used by the mp_lib2cards.sas macro.
<h4> Related Macros </h4>
@li mp_lib2cards.sas
@li mp_ds2inserts.sas
@li mp_mdtablewrite.sas
@version 9.2
@author Allan Bowe
@@ -51,7 +69,7 @@
%if (&tgt_ds = ) %then %let tgt_ds=&base_ds;
%if %index(&tgt_ds,.)=0 %then %let tgt_ds=WORK.%scan(&base_ds,2,.);
%if ("&outencoding" ne "") %then %let outencoding=encoding="&outencoding";
%if ("&append" = "") %then %let append=;
%if ("&append" = "" or "&append" = "NO") %then %let append=;
%else %let append=mod;
/* get varcount */
@@ -137,7 +155,18 @@ data datalines_2;
,put(',name,',best32.-l)
,substrn(put(',name,',bestd32.-l),1
,findc(put(',name,',bestd32.-l),"0","TBK")))');
else dataline=name;
/**
* binary data must be converted, to store in text format. It is identified
* by the presence of the $HEX keyword in the format.
*/
else if upcase(format)=:'$HEX' then
dataline=cats('put(trim(',name,'),',format,')');
/**
* There is no easy way to store line breaks in a cards file.
* To discuss this, use: https://github.com/sasjs/core/issues/80
* Removing all nonprintables with kw (keep writeable)
*/
else dataline=cats('compress(',name,', ,"kw")');
run;
proc sql noprint;
@@ -162,7 +191,8 @@ data _null_;
/* Build input statement */
if type='char' then type3=':$char.';
if upcase(format)=:'$HEX' then type3=':'!!format;
else if type='char' then type3=':$char.';
str2=put(name,$33.)||type3;
@@ -184,11 +214,12 @@ data _null_;
file &cards_file. &outencoding lrecl=32767 termstr=nl &append;
length __attrib $32767;
if _n_=1 then do;
put '/*******************************************************************';
put " Datalines for %upcase(%scan(&base_ds,2)) dataset ";
put " Generated by %nrstr(%%)mp_ds2cards()";
put " Available on github.com/sasjs/core";
put '********************************************************************/';
put '/**';
put ' @file';
put " @brief Datalines for %upcase(%scan(&base_ds,2)) dataset";
put " @details Generated by %nrstr(%%)mp_ds2cards()";
put " Available on github.com/sasjs/core";
put '**/';
put "data &tgt_ds &indexes;";
put "attrib ";
%do i = 1 %to &nvars;
@@ -212,11 +243,11 @@ data _null_;
put 'run;';
end;
else do;
put "infile cards dsd delimiter=',';";
put "infile cards dsd;";
put "input ";
%do i = 1 %to &nvars.;
%if(%length(&&input_stmt_&i..)) %then
put " &&input_stmt_&i..";
put " &&input_stmt_&i..";
;
%end;
put ";";

View File

@@ -49,8 +49,11 @@ create table &outds as
on upcase(a.TABLE_CATALOG)=upcase(b.TABLE_CATALOG)
and upcase(a.TABLE_NAME)=upcase(b.TABLE_NAME)
and a.constraint_name=b.constraint_name
where upcase(a.TABLE_CATALOG)="&lib"
and upcase(b.TABLE_CATALOG)="&lib"
/**
* We cannot apply this clause to the underlying dictionary table. See:
* https://communities.sas.com/t5/SAS-Programming/Unexpected-Where-Clause-behaviour-in-dictionary-TABLE/m-p/771554#M244867
*/
where calculated libref="&lib"
%if "&ds" ne "" %then %do;
and upcase(a.TABLE_NAME)="&ds"
and upcase(b.TABLE_NAME)="&ds"

1256
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -50,7 +50,10 @@
"appLoc": "/Shared Data/temp/macrocore",
"macroFolders": [
"tests/sas9only"
]
],
"deployConfig": {
"deployServicePack": true
}
},
{
"name": "docsonly",

View File

@@ -0,0 +1,60 @@
/**
@file
@brief Testing mp_ds2cards.sas macro
<h4> SAS Macros </h4>
@li mp_ds2cards.sas
@li mp_assert.sas
**/
/**
* test 1 - rebuild an existing dataset
* Cars is a great dataset - it contains leading spaces, and formatted numerics
*/
%mp_ds2cards(base_ds=sashelp.cars
, tgt_ds=work.test
, cards_file= "%sysfunc(pathname(work))/cars.sas"
, showlog=NO
)
%inc "%sysfunc(pathname(work))/cars.sas"/source2;
proc compare base=sashelp.cars compare=work.test;
quit;
%mp_assert(
iftrue=(&sysinfo=1),
desc=sashelp.cars is identical except for ds label,
outds=work.test_results
)
/**
* test 2 - binary data compare
*/
data work.binarybase;
format bin $hex500. z $hex.;
do x=1 to 250;
z=byte(x);
bin=trim(bin)!!z;
output;
end;
run;
%mp_ds2cards(base_ds=work.binarybase
, showlog=YES
, cards_file="%sysfunc(pathname(work))/c2.sas"
, tgt_ds=work.binarycompare
, append=
)
%inc "%sysfunc(pathname(work))/c2.sas"/source2;
proc compare base=work.binarybase compare=work.binarycompare;
run;
%mp_assert(
iftrue=(&sysinfo=0),
desc=work.binarybase dataset is identical,
outds=work.test_results
)

View File

@@ -0,0 +1,29 @@
/**
@file
@brief Testing mp_getconstraints.sas macro
<h4> SAS Macros </h4>
@li mf_nobs.sas
@li mp_getconstraints.sas
@li mp_assert.sas
**/
proc sql;
create table work.example(
TX_FROM float format=datetime19.,
DD_TYPE char(16),
DD_SOURCE char(2048),
DD_SHORTDESC char(256),
constraint pk primary key(tx_from, dd_type,dd_source),
constraint unq unique(tx_from, dd_type),
constraint nnn not null(DD_SHORTDESC)
);
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
%mp_assert(
iftrue=(%mf_nobs(work.constraints)=6),
desc=Output table work.constraints created with correct number of records,
outds=work.test_results
)