diff --git a/all.sas b/all.sas index 53f9f50..fcaba22 100644 --- a/all.sas +++ b/all.sas @@ -4093,6 +4093,103 @@ select distinct lowcase(memname) %end; %mend;/** + @file + @brief Create a Markdown Table from a dataset + @details A markdown table is a simple table representation for use in + documents written in markdown format. + + An online generator is available here: + https://www.tablesgenerator.com/markdown_tables + + This structure is also used by the Macro Core library for documenting input/ + output datasets, as well as the sasjs/cli tool for documenting inputs/outputs + for web services. + + We take the standard definition one step further by embedding the informat + in the table header row, like so: + + |var1:$|var2:best.|var3:date9.| + |---|---|---| + |some text|42|01JAN1960| + |blah|1|31DEC1999| + + Which resolves to: + + |var1:$|var2:best.|var3:date9.| + |---|---|---| + |some text|42|01JAN1960| + |blah|1|31DEC1999| + + + Usage: + + %mp_mdtablewrite(libds=sashelp.class,showlog=YES) + + +

SAS Macros

+ @li mf_getvarlist.sas + @li mf_getvarformat.sas + + @param [in] libds= the library / dataset to create or read from. + @param [out] fref= Fileref to contain the markdown. Default=mdtable. + @param [out] showlog= set to YES to show the markdown in the log. Default=NO. + + @version 9.3 + @author Allan Bowe +**/ + +%macro mp_mdtablewrite( + libds=, + fref=mdtable, + showlog=NO +)/*/STORE SOURCE*/; + +/* check fileref is assigned */ +%if %sysfunc(fileref(&fref)) > 0 %then %do; + filename &fref temp; +%end; + +%local vars; +%let vars=%mf_getvarlist(&libds); + +/* create the header row */ +data _null_; + file &fref; + length line $32767; + put '|' +%local i var fmt; +%do i=1 %to %sysfunc(countw(&vars)); + %let var=%scan(&vars,&i); + %let fmt=%mf_getvarformat(&libds,&var,force=1); + "&var:&fmt|" +%end; + ; + put '|' +%do i=1 %to %sysfunc(countw(&vars)); + "---|" +%end; + ; +run; + +/* write out the data */ +data _null_; + file &fref mod dlm='|' lrecl=32767; + set &libds ; + length line $32767; + line=cats('|',%mf_getvarlist(&libds,dlm=%str(,'|',)),'|'); + put line; +run; + +%if %upcase(&showlog)=YES %then %do; + options ps=max; + data _null_; + infile &fref; + input; + putlog _infile_; + run; +%end; + +%mend mp_mdtablewrite;/** @file @brief Logs the time the macro was executed in a control dataset. @details If the dataset does not exist, it is created. Usage: @@ -8552,9 +8649,76 @@ run; metadata and physical tables. Each output can be created with an optional prefix. + Credit - Paul Homes + https://platformadmin.com/blogs/paul/2012/11/sas-proc-metalib-ods-output - @param [in] libname the metadata name of the library to be compared - @param [out] prefix the dataset to create that contains the list of libraries + Usage: + + %* create (and assign) a library for testing purposes ; + %mm_createlibrary( + libname=My Temp Library, + libref=XXTEMPXX, + tree=/User Folders/&sysuserid, + directory=%sysfunc(pathname(work)) + ) + + %* create some tables; + data work.table1 table2 table3; + a=1;b='two';c=3; + run; + + %* register the tables; + proc metalib; + omr=(library="My Temp Library"); + report(type=detail); + update_rule (delete); + run; + + %* modify the tables; + proc sql; + drop table table3; + alter table table2 drop c; + alter table table2 add d num; + + %* run the macro; + %mm_getlibmetadiffs(libname=My Temp Library) + + %* delete the library ; + %mm_deletelibrary(name=My Temp Library) + + The program will create four output tables, with the following structure (and + example data): + + #### &prefix.added + |name:$32.|metaID:$17.|SAStabName:$32.| + |---|---|---| + |||DATA1| + + #### &prefix.deleted + |name:$32.|metaID:$17.|SAStabName:$32.| + |---|---|---| + |TABLE3|A5XLSNXI.BK0001HO|TABLE3| + + #### &prefix.updated + |tabName:$32.|tabMetaID:$17.|SAStabName:$32.|metaName:$32.|metaID:$17.|sasname:$32.|metaType:$16.|change:$64.| + |---|---|---|---|---|---|---|---| + |TABLE2|A5XLSNXI.BK0001HN|TABLE2|c|A5XLSNXI.BM000MA9|c|Column|Deleted| + ||||d||d|Column|Added| + + #### &prefix.meta + |Label1:$28.|cValue1:$1.|nValue1:D12.3| + |---|---|---| + |Total tables analyzed|4|4| + |Tables to be Updated|1|1| + |Tables to be Deleted|1|1| + |Tables to be Added|1|1| + |Tables matching data source|1|1| + |Tables not processed|0|0| + + @param [in] libname= the metadata name of the library to be compared + @param [out] outlib= The output library in which to store the output tables. + Default=WORK. + @param [out] prefix The prefix for the four tables created. Default=metadiff. @version 9.3 @author Allan Bowe @@ -8562,33 +8726,43 @@ run; **/ %macro mm_getlibmetadiffs( - prefix=metadiff + libname= , + prefix=metadiff, + outlib=work )/*/STORE SOURCE*/; + /* create tempds */ + data;run; + %local tempds; + %let tempds=&syslast; + /* save options */ + proc optsave out=&tempds; + run; options VALIDVARNAME=ANY VALIDMEMNAME=EXTEND; - - ods trace on; ods output - factoid1=s9h.&requestid.ml_all - updtab=s9h.&requestid.ml_up - addtab=s9h.&requestid.ml_add - deltab=s9h.&requestid.ml_del + factoid1=&outlib..&prefix.meta + updtab=&outlib..&prefix.updated + addtab=&outlib..&prefix.added + deltab=&outlib..&prefix.deleted ; proc metalib; - omr=(library="&libraryname"); + omr=(library="&libname"); noexec; report(type=detail); + update_rule (delete); run; ods output close; - ods trace off; + /* restore options */ + proc optload data=&tempds; + run; -%mend; +%mend mm_getlibmetadiffs; /** @file @brief Creates a dataset with all metadata libraries diff --git a/base/mp_mdtablewrite.sas b/base/mp_mdtablewrite.sas new file mode 100644 index 0000000..a5d3528 --- /dev/null +++ b/base/mp_mdtablewrite.sas @@ -0,0 +1,98 @@ +/** + @file + @brief Create a Markdown Table from a dataset + @details A markdown table is a simple table representation for use in + documents written in markdown format. + + An online generator is available here: + https://www.tablesgenerator.com/markdown_tables + + This structure is also used by the Macro Core library for documenting input/ + output datasets, as well as the sasjs/cli tool for documenting inputs/outputs + for web services. + + We take the standard definition one step further by embedding the informat + in the table header row, like so: + + |var1:$|var2:best.|var3:date9.| + |---|---|---| + |some text|42|01JAN1960| + |blah|1|31DEC1999| + + Which resolves to: + + |var1:$|var2:best.|var3:date9.| + |---|---|---| + |some text|42|01JAN1960| + |blah|1|31DEC1999| + + + Usage: + + %mp_mdtablewrite(libds=sashelp.class,showlog=YES) + + +

SAS Macros

+ @li mf_getvarlist.sas + @li mf_getvarformat.sas + + @param [in] libds= the library / dataset to create or read from. + @param [out] fref= Fileref to contain the markdown. Default=mdtable. + @param [out] showlog= set to YES to show the markdown in the log. Default=NO. + + @version 9.3 + @author Allan Bowe +**/ + +%macro mp_mdtablewrite( + libds=, + fref=mdtable, + showlog=NO +)/*/STORE SOURCE*/; + +/* check fileref is assigned */ +%if %sysfunc(fileref(&fref)) > 0 %then %do; + filename &fref temp; +%end; + +%local vars; +%let vars=%mf_getvarlist(&libds); + +/* create the header row */ +data _null_; + file &fref; + length line $32767; + put '|' +%local i var fmt; +%do i=1 %to %sysfunc(countw(&vars)); + %let var=%scan(&vars,&i); + %let fmt=%mf_getvarformat(&libds,&var,force=1); + "&var:&fmt|" +%end; + ; + put '|' +%do i=1 %to %sysfunc(countw(&vars)); + "---|" +%end; + ; +run; + +/* write out the data */ +data _null_; + file &fref mod dlm='|' lrecl=32767; + set &libds ; + length line $32767; + line=cats('|',%mf_getvarlist(&libds,dlm=%str(,'|',)),'|'); + put line; +run; + +%if %upcase(&showlog)=YES %then %do; + options ps=max; + data _null_; + infile &fref; + input; + putlog _infile_; + run; +%end; + +%mend mp_mdtablewrite; \ No newline at end of file diff --git a/meta/mm_getlibmetadiffs.sas b/meta/mm_getlibmetadiffs.sas new file mode 100644 index 0000000..82af1d3 --- /dev/null +++ b/meta/mm_getlibmetadiffs.sas @@ -0,0 +1,129 @@ +/** + @file + @brief Compares the metadata of a library with the physical tables + @details Creates a series of output tables that show the differences between + metadata and physical tables. + Each output can be created with an optional prefix. + + Credit - Paul Homes + https://platformadmin.com/blogs/paul/2012/11/sas-proc-metalib-ods-output + + Usage: + + %* create (and assign) a library for testing purposes ; + %mm_createlibrary( + libname=My Temp Library, + libref=XXTEMPXX, + tree=/User Folders/&sysuserid, + directory=%sysfunc(pathname(work)) + ) + + %* create some tables; + data work.table1 table2 table3; + a=1;b='two';c=3; + run; + + %* register the tables; + proc metalib; + omr=(library="My Temp Library"); + report(type=detail); + update_rule (delete); + run; + + %* modify the tables; + proc sql; + drop table table3; + alter table table2 drop c; + alter table table2 add d num; + + %* run the macro; + %mm_getlibmetadiffs(libname=My Temp Library) + + %* delete the library ; + %mm_deletelibrary(name=My Temp Library) + + The program will create four output tables, with the following structure (and + example data): + + #### &prefix.added + |name:$32.|metaID:$17.|SAStabName:$32.| + |---|---|---| + |||DATA1| + + #### &prefix.deleted + |name:$32.|metaID:$17.|SAStabName:$32.| + |---|---|---| + |TABLE3|A5XLSNXI.BK0001HO|TABLE3| + + #### &prefix.updated + |tabName:$32.|tabMetaID:$17.|SAStabName:$32.|metaName:$32.|metaID:$17.|sasname:$32.|metaType:$16.|change:$64.| + |---|---|---|---|---|---|---|---| + |TABLE2|A5XLSNXI.BK0001HN|TABLE2|c|A5XLSNXI.BM000MA9|c|Column|Deleted| + ||||d||d|Column|Added| + + #### &prefix.meta + |Label1:$28.|cValue1:$1.|nValue1:D12.3| + |---|---|---| + |Total tables analyzed|4|4| + |Tables to be Updated|1|1| + |Tables to be Deleted|1|1| + |Tables to be Added|1|1| + |Tables matching data source|1|1| + |Tables not processed|0|0| + + If you are interested in more functionality like this (checking the health of + SAS metadata and your SAS 9 environment) then do contact [Allan Bowe]( + https://www.linkedin.com/in/allanbowe) for details of our SAS 9 Health Check + service. + + Our system scan will perform hundreds of checks to identify common issues, + such as dangling metadata, embedded passwords, security issues and more. + + @param [in] libname= the metadata name of the library to be compared + @param [out] outlib= The output library in which to store the output tables. + Default=WORK. + @param [out] prefix The prefix for the four tables created. Default=metadiff. + + @version 9.3 + @author Allan Bowe + +**/ + +%macro mm_getlibmetadiffs( + libname= , + prefix=metadiff, + outlib=work +)/*/STORE SOURCE*/; + + /* create tempds */ + data;run; + %local tempds; + %let tempds=&syslast; + + /* save options */ + proc optsave out=&tempds; + run; + + options VALIDVARNAME=ANY VALIDMEMNAME=EXTEND; + + ods output + factoid1=&outlib..&prefix.meta + updtab=&outlib..&prefix.updated + addtab=&outlib..&prefix.added + deltab=&outlib..&prefix.deleted + ; + + proc metalib; + omr=(library="&libname"); + noexec; + report(type=detail); + update_rule (delete); + run; + + ods output close; + + /* restore options */ + proc optload data=&tempds; + run; + +%mend mm_getlibmetadiffs;