@sasjs/utils 3.5.1 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/file/file.js +4 -2
  2. package/file/file.js.map +1 -1
  3. package/macros/mf_abort.sas +7 -2
  4. package/macros/mf_deletefile.sas +1 -1
  5. package/macros/mf_existds.sas +1 -1
  6. package/macros/mf_existfileref.sas +2 -2
  7. package/macros/mf_existfunction.sas +1 -1
  8. package/macros/mf_existvar.sas +8 -4
  9. package/macros/mf_existvarlist.sas +2 -2
  10. package/macros/mf_getapploc.sas +1 -0
  11. package/macros/mf_getattrc.sas +2 -2
  12. package/macros/mf_getattrn.sas +2 -2
  13. package/macros/mf_getfmtlist.sas +3 -4
  14. package/macros/mf_getgitbranch.sas +37 -0
  15. package/macros/mf_getkeyvalue.sas +3 -2
  16. package/macros/mf_getplatform.sas +1 -1
  17. package/macros/mf_getschema.sas +1 -1
  18. package/macros/mf_getuniquelibref.sas +2 -2
  19. package/macros/mf_getuniquename.sas +1 -1
  20. package/macros/mf_getuser.sas +0 -2
  21. package/macros/mf_getvalue.sas +3 -3
  22. package/macros/mf_getvarformat.sas +2 -1
  23. package/macros/mf_getvarlen.sas +2 -2
  24. package/macros/mf_getvarnum.sas +2 -2
  25. package/macros/mf_getvartype.sas +2 -2
  26. package/macros/mf_getxengine.sas +1 -1
  27. package/macros/mf_increment.sas +2 -2
  28. package/macros/mf_isblank.sas +2 -2
  29. package/macros/mf_isdir.sas +1 -1
  30. package/macros/mf_loc.sas +6 -1
  31. package/macros/mf_mimetype.sas +436 -0
  32. package/macros/mf_mkdir.sas +1 -1
  33. package/macros/mf_mval.sas +2 -0
  34. package/macros/mf_nobs.sas +1 -1
  35. package/macros/mf_readfile.sas +63 -0
  36. package/macros/mf_trimstr.sas +2 -2
  37. package/macros/mf_wordsinstr1andstr2.sas +2 -2
  38. package/macros/mf_wordsinstr1butnotstr2.sas +2 -2
  39. package/macros/mf_writefile.sas +2 -2
  40. package/macros/mp_abort.sas +50 -13
  41. package/macros/mp_aligndecimal.sas +95 -0
  42. package/macros/mp_appendfile.sas +2 -2
  43. package/macros/mp_applyformats.sas +5 -5
  44. package/macros/mp_assert.sas +1 -1
  45. package/macros/mp_assertcols.sas +3 -3
  46. package/macros/mp_assertcolvals.sas +9 -5
  47. package/macros/mp_assertscope.sas +4 -4
  48. package/macros/mp_base64copy.sas +2 -2
  49. package/macros/mp_binarycopy.sas +7 -6
  50. package/macros/mp_chop.sas +4 -3
  51. package/macros/mp_cleancsv.sas +5 -4
  52. package/macros/mp_cntlout.sas +16 -7
  53. package/macros/mp_copyfolder.sas +2 -2
  54. package/macros/mp_createconstraints.sas +3 -3
  55. package/macros/mp_createwebservice.sas +1 -1
  56. package/macros/mp_csv2ds.sas +6 -5
  57. package/macros/mp_deleteconstraints.sas +5 -3
  58. package/macros/mp_deletefolder.sas +1 -1
  59. package/macros/mp_dictionary.sas +1 -1
  60. package/macros/mp_dirlist.sas +1 -1
  61. package/macros/mp_distinctfmtvalues.sas +5 -5
  62. package/macros/mp_ds2csv.sas +10 -1
  63. package/macros/mp_ds2ddl.sas +14 -2
  64. package/macros/mp_ds2md.sas +1 -0
  65. package/macros/mp_dsmeta.sas +2 -2
  66. package/macros/mp_filtercheck.sas +105 -16
  67. package/macros/mp_filtergenerate.sas +2 -2
  68. package/macros/mp_filterstore.sas +4 -3
  69. package/macros/mp_getcols.sas +6 -4
  70. package/macros/mp_getdbml.sas +4 -4
  71. package/macros/mp_getddl.sas +15 -10
  72. package/macros/mp_getformats.sas +13 -3
  73. package/macros/mp_gitlog.sas +104 -0
  74. package/macros/mp_gitstatus.sas +1 -1
  75. package/macros/mp_gsubfile.sas +6 -6
  76. package/macros/mp_guesspk.sas +1 -1
  77. package/macros/mp_hashdataset.sas +1 -1
  78. package/macros/mp_init.sas +1 -0
  79. package/macros/mp_lib2cards.sas +7 -7
  80. package/macros/mp_loadformat.sas +127 -47
  81. package/macros/mp_lockanytable.sas +31 -24
  82. package/macros/mp_md5.sas +3 -4
  83. package/macros/mp_perflog.sas +3 -3
  84. package/macros/mp_prevobs.sas +5 -5
  85. package/macros/mp_recursivejoin.sas +7 -6
  86. package/macros/mp_replace.sas +7 -5
  87. package/macros/mp_runddl.sas +3 -3
  88. package/macros/mp_searchcols.sas +7 -6
  89. package/macros/mp_stackdiffs.sas +1 -0
  90. package/macros/mp_storediffs.sas +8 -8
  91. package/macros/mp_stprequests.sas +4 -3
  92. package/macros/mp_stripdiffs.sas +256 -0
  93. package/macros/mp_testjob.sas +2 -2
  94. package/macros/mp_testwritespeedlibrary.sas +3 -3
  95. package/macros/mp_tree.sas +2 -2
  96. package/macros/mp_unzip.sas +5 -4
  97. package/macros/mp_updatevarlength.sas +3 -3
  98. package/macros/mp_validatecol.sas +3 -3
  99. package/macros/mp_wait4file.sas +1 -1
  100. package/macros/mp_webin.sas +1 -1
  101. package/macros/mp_zip.sas +5 -5
  102. package/package.json +5 -6
@@ -1,8 +1,20 @@
1
1
  /**
2
2
  @file
3
- @brief A wrapper for mp_getddl.sas
4
- @details In the next release, this will be the main version.
3
+ @brief Fetches DDL for a specific table
4
+ @details Uses mp_getddl under the hood
5
5
 
6
+ @param [in] libds library.dataset to create ddl for
7
+ @param [in] fref= (getddl) the fileref to which to _append_ the DDL. If it
8
+ does not exist, it will be created.
9
+ @param [in] flavour= (SAS) The type of DDL to create. Options:
10
+ @li SAS
11
+ @li TSQL
12
+
13
+ @param [in]showlog= (NO) Set to YES to show the DDL in the log
14
+ @param [in] schema= () Choose a preferred schema name (default is to use
15
+ actual schema, else libref)
16
+ @param [in] applydttm= (NO) For non SAS DDL, choose if columns are created with
17
+ native datetime2 format or regular decimal type
6
18
 
7
19
  <h4> SAS Macros </h4>
8
20
  @li mp_getddl.sas
@@ -95,6 +95,7 @@ run;
95
95
  options ps=max lrecl=max;
96
96
  data _null_;
97
97
  infile &outref;
98
+ if _n_=1 then putlog "# &libds" /;
98
99
  input;
99
100
  putlog _infile_;
100
101
  run;
@@ -49,8 +49,8 @@
49
49
  https://support.sas.com/resources/papers/proceedings14/1549-2014.pdf) by
50
50
  [Louise Hadden](https://www.linkedin.com/in/louisehadden/).
51
51
 
52
- @param libds The library.dataset to export the metadata for
53
- @param outds= (work.dsmeta) The output table to contain the metadata
52
+ @param [in] libds The library.dataset to export the metadata for
53
+ @param [out] outds= (work.dsmeta) The output table to contain the metadata
54
54
 
55
55
  <h4> Related Files </h4>
56
56
  @li mp_dsmeta.test.sas
@@ -37,10 +37,12 @@
37
37
  @param [in] targetds= The target dataset against which to verify VARIABLE_NM.
38
38
  This must be available (ie, the library must be assigned).
39
39
  @param [out] abort= (YES) If YES will call mp_abort.sas on any exceptions
40
- @param [out] outds= The output table, which is a copy of the &inds. table
41
- plus a REASON_CD column, containing only bad records. If bad records found,
42
- the SYSCC value will be set to 1008 (general data problem). Downstream
43
- processes should check this table (and return code) before continuing.
40
+ @param [out] outds= (work.badrecords) The output table, which is a copy of the
41
+ &inds. table plus a REASON_CD column, containing only bad records.
42
+ If bad records are found, the SYSCC value will be set to 1008
43
+ (a general data problem).
44
+ Downstream processes should check this table (and return code) before
45
+ continuing.
44
46
 
45
47
  <h4> SAS Macros </h4>
46
48
  @li mp_abort.sas
@@ -84,15 +86,14 @@
84
86
  /**
85
87
  * Sanitise the values based on valid value lists, then strip out
86
88
  * quotes, commas, periods and spaces.
87
- * Only numeric values should remain
88
89
  */
89
90
  %local reason_cd nobs;
90
91
  %let nobs=0;
91
92
  data &outds;
92
93
  /*length GROUP_LOGIC SUBGROUP_LOGIC $3 SUBGROUP_ID 8 VARIABLE_NM $32
93
94
  OPERATOR_NM $10 RAW_VALUE $4000;*/
94
- set &inds;
95
- length reason_cd $4032 vtype $1 vnum dsid 8 tmp $4000;
95
+ set &inds end=last;
96
+ length reason_cd $4032 vtype vtype2 $1 vnum dsid 8 tmp $4000;
96
97
  drop tmp;
97
98
 
98
99
  /* quick check to ensure column exists */
@@ -108,7 +109,8 @@ data &outds;
108
109
  end;
109
110
 
110
111
  /* need to open the dataset to get the column type */
111
- dsid=open("&targetds","i");
112
+ retain dsid;
113
+ if _n_=1 then dsid=open("&targetds","i");
112
114
  if dsid>0 then do;
113
115
  vnum=varnum(dsid,VARIABLE_NM);
114
116
  if vnum<1 then do;
@@ -118,11 +120,19 @@ data &outds;
118
120
  call symputx('reason_cd',reason_cd,'l');
119
121
  call symputx('nobs',_n_,'l');
120
122
  output;
121
- return;
123
+ goto endstep;
122
124
  end;
123
125
  /* now we can get the type */
124
126
  else vtype=vartype(dsid,vnum);
125
127
  end;
128
+ else do;
129
+ REASON_CD=cats("Could not open &targetds");
130
+ putlog REASON_CD= dsid=;
131
+ call symputx('reason_cd',reason_cd,'l');
132
+ call symputx('nobs',_n_,'l');
133
+ output;
134
+ stop;
135
+ end;
126
136
 
127
137
  /* closed list checks */
128
138
  if GROUP_LOGIC not in ('AND','OR') then do;
@@ -157,15 +167,40 @@ data &outds;
157
167
  end;
158
168
 
159
169
  /* special missing logic */
160
- if vtype='N'
161
- and OPERATOR_NM in ('=','>','<','<=','>=','NE','GE','LE')
162
- and cats(upcase(raw_value)) in (
170
+ if vtype='N' & OPERATOR_NM in ('=','>','<','<=','>=','NE','GE','LE') then do;
171
+ if cats(upcase(raw_value)) in (
163
172
  '.','.A','.B','.C','.D','.E','.F','.G','.H','.I','.J','.K','.L','.M','.N'
164
173
  '.N','.O','.P','.Q','.R','.S','.T','.U','.V','.W','.X','.Y','.Z','._'
165
174
  )
166
- then do;
167
- /* valid numeric - exit data step loop */
168
- return;
175
+ then do;
176
+ /* valid numeric - exit data step loop */
177
+ return;
178
+ end;
179
+ else if subpad(upcase(raw_value),1,1) in (
180
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N'
181
+ 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_'
182
+ )
183
+ then do;
184
+ /* check if the raw_value contains a valid variable NAME */
185
+ vnum=varnum(dsid,subpad(raw_value,1,32));
186
+ if vnum>0 then do;
187
+ /* now we can get the type */
188
+ vtype2=vartype(dsid,vnum);
189
+ /* check type matches */
190
+ if vtype2=vtype then do;
191
+ /* valid target var - exit loop */
192
+ return;
193
+ end;
194
+ else do;
195
+ REASON_CD=cats("Compared Type (",vtype2,") is not (",vtype,")");
196
+ putlog REASON_CD= dsid=;
197
+ call symputx('reason_cd',reason_cd,'l');
198
+ call symputx('nobs',_n_,'l');
199
+ output;
200
+ goto endstep;
201
+ end;
202
+ end;
203
+ end;
169
204
  end;
170
205
 
171
206
  /* special logic */
@@ -187,6 +222,32 @@ data &outds;
187
222
  if vtype='N' then do i=1 to countc(raw_value1, ',')+1;
188
223
  tmp=scan(raw_value1,i,',');
189
224
  if cats(tmp) ne '.' and input(tmp, ?? 8.) eq . then do;
225
+ if OPERATOR_NM ='BETWEEN' and subpad(upcase(tmp),1,1) in (
226
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N'
227
+ 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_'
228
+ )
229
+ then do;
230
+ /* check if the raw_value contains a valid variable NAME */
231
+ /* is not valid syntax for IN or NOT IN */
232
+ vnum=varnum(dsid,subpad(tmp,1,32));
233
+ if vnum>0 then do;
234
+ /* now we can get the type */
235
+ vtype2=vartype(dsid,vnum);
236
+ /* check type matches */
237
+ if vtype2=vtype then do;
238
+ /* valid target var - exit loop */
239
+ return;
240
+ end;
241
+ else do;
242
+ REASON_CD=cats("Compared Type (",vtype2,") is not (",vtype,")");
243
+ putlog REASON_CD= dsid=;
244
+ call symputx('reason_cd',reason_cd,'l');
245
+ call symputx('nobs',_n_,'l');
246
+ output;
247
+ goto endstep;
248
+ end;
249
+ end;
250
+ end;
190
251
  REASON_CD='Non Numeric value provided';
191
252
  putlog REASON_CD= OPERATOR_NM= raw_value= raw_value1= ;
192
253
  call symputx('reason_cd',reason_cd,'l');
@@ -211,14 +272,42 @@ data &outds;
211
272
 
212
273
  /* output records that contain values other than digits and spaces */
213
274
  if notdigit(compress(raw_value3,' '))>0 then do;
275
+ if vtype='C' and subpad(upcase(raw_value),1,1) in (
276
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N'
277
+ 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_'
278
+ )
279
+ then do;
280
+ /* check if the raw_value contains a valid variable NAME */
281
+ vnum=varnum(dsid,subpad(raw_value,1,32));
282
+ if vnum>0 then do;
283
+ /* now we can get the type */
284
+ vtype2=vartype(dsid,vnum);
285
+ /* check type matches */
286
+ if vtype2=vtype then do;
287
+ /* valid target var - exit loop */
288
+ return;
289
+ end;
290
+ else do;
291
+ REASON_CD=cats("Compared Char Type (",vtype2,") is not (",vtype,")");
292
+ putlog REASON_CD= dsid=;
293
+ call symputx('reason_cd',reason_cd,'l');
294
+ call symputx('nobs',_n_,'l');
295
+ output;
296
+ goto endstep;
297
+ end;
298
+ end;
299
+ end;
300
+
214
301
  putlog raw_value3= $hex32.;
215
302
  REASON_CD=cats('Invalid RAW_VALUE:',raw_value);
216
- putlog REASON_CD= raw_value= raw_value1= raw_value2= raw_value3=;
303
+ putlog (_all_)(=);
217
304
  call symputx('reason_cd',reason_cd,'l');
218
305
  call symputx('nobs',_n_,'l');
219
306
  output;
220
307
  end;
221
308
 
309
+ endstep:
310
+ if last then rc=close(dsid);
222
311
  run;
223
312
 
224
313
 
@@ -51,8 +51,8 @@
51
51
  > )
52
52
 
53
53
  @param [in] inds The input table with query values
54
- @param [out] outref= The output fileref to contain the filter clause. Will
55
- be created (or replaced).
54
+ @param [out] outref= (filter) The output fileref to contain the filter clause.
55
+ Will be created (or replaced).
56
56
 
57
57
  <h4> Related Macros </h4>
58
58
  @li mp_filtercheck.sas
@@ -44,9 +44,10 @@
44
44
  mp_coretable.sas as follows: `mp_coretable(LOCKTABLE)`.
45
45
  @param [in] maxkeytable= (0) Optional permanent reference table used for
46
46
  retained key tracking. Described in mp_retainedkey.sas.
47
- @param [in] mdebug= set to 1 to enable DEBUG messages
48
- @param [out] outresult= The result table with the FILTER_RK
49
- @param [out] outquery= The original query, taken as extract after table load
47
+ @param [in] mdebug= (1) set to 1 to enable DEBUG messages
48
+ @param [out] outresult= (work.result) The result table with the FILTER_RK
49
+ @param [out] outquery= (work.query) The original query, taken as extract
50
+ after table load
50
51
 
51
52
 
52
53
  <h4> SAS Macros </h4>
@@ -12,14 +12,15 @@
12
12
 
13
13
  %mp_getcols(sashelp.airline,outds=work.myds)
14
14
 
15
- @param ds The dataset from which to obtain column metadata
16
- @param outds= (work.cols) The output dataset to create. Sample data:
15
+ @param [in] ds The dataset from which to obtain column metadata
16
+ @param [out] outds= (work.cols) The output dataset to create. Sample data:
17
17
  |NAME:$32.|LENGTH:best.|VARNUM:best.|LABEL:$256.|FMTNAME:$32.|FORMAT:$49.|TYPE:$1.|DDTYPE:$9.|
18
18
  |---|---|---|---|---|---|---|---|
19
19
  |`AIR `|`8 `|`2 `|`international airline travel (thousands) `|` `|`8. `|`N `|`NUMERIC `|
20
20
  |`DATE `|`8 `|`1 `|`DATE `|`MONYY `|`MONYY. `|`N `|`DATE `|
21
21
  |`REGION `|`3 `|`3 `|`REGION `|` `|`$3. `|`C `|`CHARACTER `|
22
22
 
23
+
23
24
  <h4> Related Macros </h4>
24
25
  @li mf_getvarlist.sas
25
26
  @li mm_getcols.sas
@@ -52,10 +53,11 @@ data &outds(keep=name type length varnum format label ddtype fmtname);
52
53
  else if formatd=0 then format=cats(fmtname,formatl,'.');
53
54
  else format=cats(fmtname,formatl,'.',formatd);
54
55
  type='N';
55
- if format=:'DATETIME' or format=:'E8601DT' then ddtype='DATETIME';
56
+ if format=:'DATETIME' or format=:'E8601DT' or format=:'NLDATM'
57
+ then ddtype='DATETIME';
56
58
  else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
57
59
  or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA'
58
- or format=:'MONYY'
60
+ or format=:'MONYY' or format=:'NLDATE'
59
61
  then ddtype='DATE';
60
62
  else if format=:'TIME' then ddtype='TIME';
61
63
  else ddtype='NUMERIC';
@@ -23,10 +23,10 @@
23
23
  @li mf_getquotedstr.sas
24
24
  @li mp_getconstraints.sas
25
25
 
26
- @param liblist= Space seperated list of librefs to take as
27
- input (Default=SASHELP)
28
- @param outref= Fileref to contain the DBML (Default=getdbml)
29
- @param showlog= set to YES to show the DBML in the log (Default is NO)
26
+ @param [in] liblist= (SASHELP) Space seperated list of librefs to take as
27
+ input
28
+ @param [out] outref= (getdbml) Fileref to contain the DBML
29
+ @param [in] showlog= (NO) set to YES to show the DBML in the log
30
30
 
31
31
  @version 9.3
32
32
  @author Allan Bowe
@@ -22,16 +22,21 @@
22
22
  @li mf_getvarcount.sas
23
23
  @li mp_getconstraints.sas
24
24
 
25
- @param lib libref of the library to create DDL for. Should be assigned.
26
- @param ds dataset to create ddl for (optional)
27
- @param fref= the fileref to which to _append_ the DDL. If it does not exist,
28
- it will be created.
29
- @param flavour= The type of DDL to create (default=SAS). Supported=TSQL
30
- @param showlog= Set to YES to show the DDL in the log
31
- @param schema= Choose a preferred schema name (default is to use actual schema
32
- ,else libref)
33
- @param applydttm= for non SAS DDL, choose if columns are created with native
34
- datetime2 format or regular decimal type
25
+ @param [in] libref Libref of the library to create DDL for. Should already
26
+ be assigned.
27
+ @param [in] ds dataset to create ddl for (optional)
28
+ @param [in] fref= (getddl) the fileref to which to _append_ the DDL. If it
29
+ does not exist, it will be created.
30
+ @param [in] flavour= (SAS) The type of DDL to create. Options:
31
+ @li SAS
32
+ @li TSQL
33
+
34
+ @param [in]showlog= (NO) Set to YES to show the DDL in the log
35
+ @param [in] schema= () Choose a preferred schema name (default is to use
36
+ actual schema, else libref)
37
+ @param [in] applydttm= (NO) For non SAS DDL, choose if columns are created
38
+ with native datetime2 format or regular decimal type
39
+
35
40
  @version 9.3
36
41
  @author Allan Bowe
37
42
  **/
@@ -7,10 +7,15 @@
7
7
  Formats are taken from the library / dataset reference and / or a static
8
8
  format list.
9
9
 
10
+ Note - the source for this information is the dictionary.formats table. This
11
+ cannot show formats that are not already declared in the FMTSEARCH path.
12
+
10
13
  Example usage:
11
14
 
12
15
  %mp_getformats(lib=sashelp,ds=prdsale,outsummary=work.dictable)
13
16
 
17
+ %mp_getformats(fmtlist=FORMAT1 $FORMAT2 @INFMT3,outsummary=work.table2)
18
+
14
19
  @param [in] lib= (0) The libref for which to return formats.
15
20
  @todo Enable exporting of formats for an entire library
16
21
  @param [in] ds= (0) The dataset from which to obtain format definitions
@@ -49,7 +54,9 @@ https://support.sas.com/documentation/cdl/en/proc/61895/HTML/default/viewer.htm#
49
54
 
50
55
 
51
56
  <h4> Related Macros </h4>
57
+ @li mf_getfmtlist.sas
52
58
  @li mp_applyformats.sas
59
+ @li mp_cntlout.sas
53
60
  @li mp_getformats.test.sas
54
61
 
55
62
  @version 9.2
@@ -66,7 +73,7 @@ https://support.sas.com/documentation/cdl/en/proc/61895/HTML/default/viewer.htm#
66
73
 
67
74
  %local i fmt allfmts tempds fmtcnt;
68
75
 
69
- %if "&fmtlist" ne "0" %then %do i=1 %to %sysfunc(countw(&fmtlist,,%str( )));
76
+ %if "&fmtlist" ne "0" %then %do i=1 %to %sysfunc(countw(&fmtlist,%str( )));
70
77
  /* ensure format list contains format _name_ only */
71
78
  %let fmt=%scan(&fmtlist,&i,%str( ));
72
79
  %let fmt=%mf_getfmtname(&fmt);
@@ -90,8 +97,7 @@ https://support.sas.com/documentation/cdl/en/proc/61895/HTML/default/viewer.htm#
90
97
  proc sql;
91
98
  create table &outsummary as
92
99
  select * from dictionary.formats
93
- where fmtname in (%mf_getquotedstr(&allfmts,quote=D))
94
- and fmttype='F';
100
+ where fmtname in (%mf_getquotedstr(&allfmts,quote=D));
95
101
 
96
102
  %if "&outdetail" ne "0" %then %do;
97
103
  /* ensure base table always exists */
@@ -115,6 +121,10 @@ create table &outsummary as
115
121
  data &tempds;
116
122
  if 0 then set &outdetail;
117
123
  set &tempds;
124
+ /* set fmtrow (position of record within the format) */
125
+ by type fmtname notsorted;
126
+ if first.fmtname then fmtrow=1;
127
+ else fmtrow+1;
118
128
  run;
119
129
  proc append base=&outdetail data=&tempds ;
120
130
  run;
@@ -0,0 +1,104 @@
1
+ /**
2
+ @file
3
+ @brief Creates a dataset with the commit history of a local repository
4
+ @details Returns the commit history from a local repository. The name of the
5
+ branch is also returned.
6
+
7
+ More details here:
8
+ https://documentation.sas.com/doc/ko/pgmsascdc/v_033/lefunctionsref/n1qo5miyvry1nen111js203hlwrh.htm
9
+
10
+ Usage:
11
+
12
+ %let gitdir=%sysfunc(pathname(work))/core;
13
+ %let repo=https://github.com/sasjs/core;
14
+ %put source clone rc=%sysfunc(GITFN_CLONE(&repo,&dir));
15
+
16
+ %mp_gitlog(&gitdir,outds=work.mp_gitlog)
17
+
18
+ @param [in] gitdir The directory containing the GIT repository
19
+ @param [in] filter= (BRANCHONLY) To return only the commits for the current
20
+ branch, use BRANCHONLY (the default). Anything else will return the entire
21
+ commit history.
22
+ @param [out] outds= (work.mp_gitlog) The output dataset to create.
23
+ All vars are $128 except `message` which is $4000.
24
+ @li author returns the author who submitted the commit.
25
+ @li children_ids returns a list of the children commit IDs
26
+ @li committer returns the name of the committer.
27
+ @li committer_email returns the email of the committer.
28
+ @li email returns the email of the commit author.
29
+ @li id returns the commit ID of the commit object.
30
+ @li in_current_branch returns "TRUE" or "FALSE" to indicate if the commit is
31
+ in the current branch.
32
+ @li message returns the commit message.
33
+ @li parent_ids returns a list of the parent commit IDs.
34
+ @li stash returns "TRUE" or "FALSE" to indicate if the commit is a stash
35
+ commit.
36
+ @li time returns the time of the commit as numeric string
37
+ @li commit_time_num time of the commit as numeric SAS datetime
38
+ @li commit_time_str the commit_time_num variable cast as string
39
+
40
+ @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
41
+ @param [in] nobs= (0) Set to an integer greater than 0 to restrict the number
42
+ of rows returned
43
+
44
+ <h4> SAS Macros </h4>
45
+ @li mf_getgitbranch.sas
46
+
47
+ <h4> Related Files </h4>
48
+ @li mp_gitadd.sas
49
+ @li mp_gitreleaseinfo.sas
50
+ @li mp_gitstatus.sas
51
+
52
+ **/
53
+
54
+ %macro mp_gitlog(gitdir,outds=work.mp_gitlog,mdebug=0,filter=BRANCHONLY,nobs=0);
55
+
56
+ %local varlist i var;
57
+ %let varlist=author children_ids committer committer_email email id
58
+ in_current_branch parent_ids stash time ;
59
+
60
+ data &outds;
61
+ LENGTH gitdir branch $ 1024 message $4000 &varlist $128 commit_time_num 8.
62
+ commit_time_str $32;
63
+ call missing (of _all_);
64
+ branch="%mf_getgitbranch(&gitdir)";
65
+ gitdir=symget('gitdir');
66
+ rc=git_status_free(trim(gitdir));
67
+ if rc=-1 then do;
68
+ put "The libgit2 library is unavailable and no Git operations can be used.";
69
+ put "See: https://stackoverflow.com/questions/74082874";
70
+ stop;
71
+ end;
72
+ else if rc=-2 then do;
73
+ put "The libgit2 library is available, but the status function failed.";
74
+ put "See the log for details.";
75
+ stop;
76
+ end;
77
+ entries=git_commit_log(trim(gitdir));
78
+ do n=1 to entries;
79
+
80
+ %do i=1 %to %sysfunc(countw(&varlist message));
81
+ %let var=%scan(&varlist message,&i,%str( ));
82
+ rc=git_commit_get(n,trim(gitdir),"&var",&var);
83
+ %end;
84
+ /* convert unix time to SAS time - https://4gl.uk/corelink0 */
85
+ /* Number of seconds between 01JAN1960 and 01JAN1970: 315619200 */
86
+ format commit_time_num datetime19.;
87
+ commit_time_num=sum(input(cats(time),best.),315619200);
88
+ commit_time_str=put(commit_time_num,datetime19.);
89
+ %if &mdebug=1 %then %do;
90
+ putlog (_all_)(=);
91
+ %end;
92
+ if "&filter"="BRANCHONLY" then do;
93
+ if cats(in_current_branch)='TRUE' then output;
94
+ end;
95
+ else output;
96
+ %if &nobs>0 %then %do;
97
+ if n ge &nobs then stop;
98
+ %end;
99
+ end;
100
+ rc=git_commit_free(trim(gitdir));
101
+ keep gitdir branch &varlist message time commit_time_num commit_time_str;
102
+ run;
103
+
104
+ %mend mp_gitlog;
@@ -60,7 +60,7 @@ data &outds;
60
60
  putlog (_all_)(=);
61
61
  %end;
62
62
  end;
63
- rc=git_status_free(gitdir);
63
+ rc=git_status_free(trim(gitdir));
64
64
  drop rc cnt;
65
65
  run;
66
66
 
@@ -22,15 +22,15 @@
22
22
  list;
23
23
  run;
24
24
 
25
- @param file= (0) The file to perform the substitution on
26
- @param patternvar= A macro variable containing the Lua
25
+ @param [in] file= (0) The file to perform the substitution on
26
+ @param [in] patternvar= A macro variable containing the Lua
27
27
  [pattern](https://www.lua.org/pil/20.2.html) to search for. Due to the use
28
28
  of special (magic) characters in Lua patterns, it is safer to pass the NAME
29
29
  of the macro variable containing the string, rather than the value itself.
30
- @param replacevar= The name of the macro variable containing the replacement
31
- _string_.
32
- @param outfile= (0) The file to write the output to. If zero, then the file
33
- is overwritten in-place.
30
+ @param [in] replacevar= ()
31
+ The name of the macro variable containing the replacement _string_.
32
+ @param [out] outfile= (0) The file to write the output to.
33
+ If zero, then the file is overwritten in-place.
34
34
 
35
35
  <h4> SAS Macros </h4>
36
36
  @li ml_gsubfile.sas
@@ -18,7 +18,7 @@
18
18
  %mp_guesspk(sashelp.class,outds=classpks)
19
19
 
20
20
  @param [in] baseds The dataset to analyse
21
- @param [out] outds= The output dataset to contain the possible PKs
21
+ @param [out] outds= (mp_guesspk) Output dataset to contain the possible PKs
22
22
  @param [in] max_guesses= (3) The total number of possible primary keys to
23
23
  generate. A table may have multiple (unlikely) PKs, so no need to list them
24
24
  all.
@@ -24,7 +24,7 @@
24
24
  @li mp_hashdirectory.sas
25
25
 
26
26
  @param [in] libds dataset to hash
27
- @param [in] salt= Provide a salt (could be, for instance, the dataset name)
27
+ @param [in] salt= () Provide a salt (could be, for instance, the dataset name)
28
28
  @param [in] iftrue= (1=1) A condition under which the macro should be executed
29
29
  @param [out] outds= (work._data_) The output dataset to create. This
30
30
  will contain one column (hashkey) with one observation (a $hex32.
@@ -70,6 +70,7 @@ options
70
70
  %if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
71
71
  noautocorrect /* disallow misspelled procedure names */
72
72
  dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
73
+ /* turn off with dsoptions=nonote2err */
73
74
  %end;
74
75
  ;
75
76
 
@@ -24,19 +24,19 @@
24
24
  @li mf_trimstr.sas
25
25
  @li mp_ds2cards.sas
26
26
 
27
- @param [in] lib= Library in which to convert all datasets
28
- @param [out] outloc= Location in which to store output. Defaults to WORK
29
- library. No quotes.
30
- @param [out] outfile= Optional output file NAME - if provided, then will create
31
- a single output file instead of one file per input table.
32
- @param [in] maxobs= limit output to the first <code>maxobs</code> observations
27
+ @param [in] lib= () Library in which to convert all datasets
28
+ @param [out] outloc= (%sysfunc(pathname(work))) Location in which to store
29
+ output. No quotes.
30
+ @param [out] outfile= (0) Optional output file NAME - if provided, then
31
+ will create a single output file instead of one file per input table.
32
+ @param [in] maxobs= (max) limit output to the first <code>maxobs</code> rows
33
33
 
34
34
  @version 9.2
35
35
  @author Allan Bowe
36
36
  **/
37
37
 
38
38
  %macro mp_lib2cards(lib=
39
- ,outloc=%sysfunc(pathname(work)) /* without trailing slash */
39
+ ,outloc=%sysfunc(pathname(work))
40
40
  ,maxobs=max
41
41
  ,random_sample=NO
42
42
  ,outfile=0