@sasjs/utils 3.6.1 → 3.6.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 (54) hide show
  1. package/.github/workflows/dependency-staleness.yml +46 -0
  2. package/.github/workflows/publish.yml +20 -1
  3. package/.github/workflows/run-tests-windows.yml +6 -3
  4. package/.github/workflows/run-tests.yml +9 -3
  5. package/auth/auth.js +2 -5
  6. package/auth/auth.js.map +1 -1
  7. package/file/file.d.ts +6 -0
  8. package/file/file.js +28 -1
  9. package/file/file.js.map +1 -1
  10. package/file/index.d.ts +1 -1
  11. package/file/index.js +2 -1
  12. package/file/index.js.map +1 -1
  13. package/input/validators.js +2 -8
  14. package/input/validators.js.map +1 -1
  15. package/logger/logger.js +8 -8
  16. package/logger/logger.js.map +1 -1
  17. package/macros/mf_getuniquelibref.sas +2 -4
  18. package/macros/mf_getvalue.sas +24 -9
  19. package/macros/mp_abort.sas +8 -2
  20. package/macros/mp_assert.sas +2 -2
  21. package/macros/mp_assertcols.sas +6 -4
  22. package/macros/mp_assertcolvals.sas +2 -2
  23. package/macros/mp_assertdsobs.sas +2 -2
  24. package/macros/mp_assertscope.sas +2 -2
  25. package/macros/mp_ds2csv.sas +2 -2
  26. package/macros/mp_ds2ddl.sas +388 -24
  27. package/macros/mp_dsmeta.sas +1 -1
  28. package/macros/mp_filterstore.sas +3 -3
  29. package/macros/mp_getmaxvarlengths.sas +1 -1
  30. package/macros/mp_jsonout.sas +2 -1
  31. package/macros/mp_lib2inserts.sas +1 -1
  32. package/macros/mp_retainedkey.sas +4 -4
  33. package/macros/mp_stackdiffs.sas +3 -3
  34. package/macros/mp_storediffs.sas +1 -1
  35. package/macros/mp_validatecol.sas +19 -2
  36. package/package.json +12 -17
  37. package/sasjsCli/getDependencies.js +1 -5
  38. package/sasjsCli/getDependencies.js.map +1 -1
  39. package/sasjsCli/getDependencyPaths.js +1 -5
  40. package/sasjsCli/getDependencyPaths.js.map +1 -1
  41. package/types/targetValidators.js +4 -9
  42. package/types/targetValidators.js.map +1 -1
  43. package/utils/index.d.ts +1 -1
  44. package/utils/index.js +3 -1
  45. package/utils/index.js.map +1 -1
  46. package/utils/url.d.ts +2 -0
  47. package/utils/url.js +14 -1
  48. package/utils/url.js.map +1 -1
  49. package/.github/dependabot.yml +0 -7
  50. package/.github/workflows/dependabot-auto-approve.yml +0 -21
  51. package/.github/workflows/dependabot-auto-merge.yml +0 -23
  52. package/macros/mp_coretable.sas +0 -73
  53. package/macros/mp_getddl.sas +0 -405
  54. package/macros/mp_testservice.sas +0 -39
@@ -1,42 +1,406 @@
1
1
  /**
2
- @file
3
- @brief Fetches DDL for a specific table
4
- @details Uses mp_getddl under the hood
2
+ @file mp_ds2ddl.sas
3
+ @brief Extract DDL in various formats, by table or library
4
+ @details Data Definition Language relates to a set of SQL instructions used
5
+ to create tables in SAS or a database. The macro can be used at table or
6
+ library level. The default behaviour is to create DDL in SAS format.
5
7
 
6
- @param [in] libds library.dataset to create ddl for
8
+ Note - views are not currently supported.
9
+
10
+ Usage:
11
+
12
+ data test(index=(pk=(x y)/unique /nomiss));
13
+ x=1;
14
+ y='blah';
15
+ label x='blah';
16
+ run;
17
+ proc sql; describe table &syslast;
18
+ %mp_ds2ddl(work,test,flavour=tsql,showlog=YES)
19
+
20
+ <h4> SAS Macros </h4>
21
+ @li mf_existfileref.sas
22
+ @li mf_getvarcount.sas
23
+ @li mp_getconstraints.sas
24
+
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)
7
28
  @param [in] fref= (getddl) the fileref to which to _append_ the DDL. If it
8
29
  does not exist, it will be created.
9
30
  @param [in] flavour= (SAS) The type of DDL to create. Options:
10
31
  @li SAS
11
32
  @li TSQL
33
+ @li PGSQL
12
34
 
13
- @param [in]showlog= (NO) Set to YES to show the DDL in the log
35
+ @param [in]showlog= (YES) Set to NO to prevent the DDL showing in the log
14
36
  @param [in] schema= () Choose a preferred schema name (default is to use
15
37
  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
18
-
19
- <h4> SAS Macros </h4>
20
- @li mp_getddl.sas
38
+ @param [in] applydttm= (NO) For non SAS DDL, choose if columns are created
39
+ with native datetime2 format or regular decimal type
21
40
 
41
+ @version 9.3
42
+ @author Allan Bowe
22
43
  **/
23
44
 
24
- %macro mp_ds2ddl(libds,fref=getddl,flavour=SAS,showlog=YES,schema=
45
+ %macro mp_ds2ddl(libref,ds,fref=getddl,flavour=SAS,showlog=YES,schema=
25
46
  ,applydttm=NO
26
47
  )/*/STORE SOURCE*/;
27
48
 
28
- %local libref;
29
- %let libds=%upcase(&libds);
30
- %let libref=%scan(&libds,1,.);
31
- %if &libref=&libds %then %let libds=WORK.&libds;
32
-
33
- %mp_getddl(%scan(&libds,1,.)
34
- ,%scan(&libds,2,.)
35
- ,fref=&fref
36
- ,flavour=SAS
37
- ,showlog=&showlog
38
- ,schema=&schema
39
- ,applydttm=&applydttm
40
- )
49
+ /* check fileref is assigned */
50
+ %if %mf_existfileref(&fref)=0 %then %do;
51
+ filename &fref temp ;
52
+ %end;
53
+
54
+ %if %length(&libref)=0 %then %let libref=WORK;
55
+ %let flavour=%upcase(&flavour);
56
+
57
+ proc sql noprint;
58
+ create table _data_ as
59
+ select * from dictionary.tables
60
+ where upcase(libname)="%upcase(&libref)"
61
+ and memtype='DATA' /* views not currently supported */
62
+ %if %length(&ds)>0 %then %do;
63
+ and upcase(memname)="%upcase(&ds)"
64
+ %end;
65
+ ;
66
+ %local tabinfo; %let tabinfo=&syslast;
67
+
68
+ create table _data_ as
69
+ select * from dictionary.columns
70
+ where upcase(libname)="%upcase(&libref)"
71
+ %if %length(&ds)>0 %then %do;
72
+ and upcase(memname)="%upcase(&ds)"
73
+ %end;
74
+ ;
75
+ %local colinfo; %let colinfo=&syslast;
76
+
77
+ %local dsnlist;
78
+ select distinct upcase(memname) into: dsnlist
79
+ separated by ' '
80
+ from &syslast
81
+ ;
82
+
83
+ create table _data_ as
84
+ select * from dictionary.indexes
85
+ where upcase(libname)="%upcase(&libref)"
86
+ %if %length(&ds)>0 %then %do;
87
+ and upcase(memname)="%upcase(&ds)"
88
+ %end;
89
+ order by idxusage, indxname, indxpos
90
+ ;
91
+ %local idxinfo; %let idxinfo=&syslast;
92
+
93
+ /* Extract all Primary Key and Unique data constraints */
94
+ %mp_getconstraints(lib=%upcase(&libref),ds=%upcase(&ds),outds=_data_)
95
+ %local colconst; %let colconst=&syslast;
96
+
97
+ %local constraints_used;
98
+ %macro addConst();
99
+ data _null_;
100
+ length ctype $11 constraint_name_orig $256 constraints_used $5000;
101
+ set &colconst(
102
+ where=(table_name="&curds" and constraint_type in ('PRIMARY','UNIQUE'))
103
+ ) end=last;
104
+ file &fref mod;
105
+ by constraint_type constraint_name;
106
+ retain constraints_used;
107
+ constraint_name_orig=constraint_name;
108
+ if upcase(strip(constraint_type)) = 'PRIMARY' then ctype='PRIMARY KEY';
109
+ else ctype=strip(constraint_type);
110
+ %if &flavour=TSQL %then %do;
111
+ column_name=catt('[',column_name,']');
112
+ constraint_name=catt('[',constraint_name,']');
113
+ %end;
114
+ %else %if &flavour=PGSQL %then %do;
115
+ column_name=catt('"',column_name,'"');
116
+ constraint_name=catt('"',constraint_name,'"');
117
+ %end;
118
+ if first.constraint_name then do;
119
+ constraints_used = catx(' ', constraints_used, constraint_name_orig);
120
+ put " ,CONSTRAINT " constraint_name ctype "(" ;
121
+ put ' ' column_name;
122
+ end;
123
+ else put ' ,' column_name;
124
+ if last.constraint_name then do;
125
+ put " )";
126
+ call symput('constraints_used',strip(constraints_used));
127
+ end;
128
+ run;
129
+ %put &=constraints_used;
130
+ %mend addConst;
131
+
132
+ data _null_;
133
+ file &fref mod;
134
+ put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */";
135
+ run;
136
+
137
+ %local x curds;
138
+ %if &flavour=SAS %then %do;
139
+ %do x=1 %to %sysfunc(countw(&dsnlist));
140
+ %let curds=%scan(&dsnlist,&x);
141
+ data _null_;
142
+ file &fref mod;
143
+ put "/* SAS Flavour DDL for %upcase(&libref).&curds */";
144
+ put "proc sql;";
145
+ run;
146
+ data _null_;
147
+ file &fref mod;
148
+ length lab $1024 typ $20;
149
+ set &colinfo (where=(upcase(memname)="&curds")) end=last;
150
+
151
+ if _n_=1 then do;
152
+ if memtype='DATA' then do;
153
+ put "create table &libref..&curds(";
154
+ end;
155
+ else do;
156
+ /* just a placeholder - we filter out views at the top */
157
+ put "create view &libref..&curds(";
158
+ end;
159
+ put " "@@;
160
+ end;
161
+ else put " ,"@@;
162
+ if length(format)>1 then fmt=" format="!!cats(format);
163
+ if length(label)>1 then
164
+ lab=" label="!!cats("'",tranwrd(label,"'","''"),"'");
165
+ if notnull='yes' then notnul=' not null';
166
+ if type='char' then typ=cats('char(',length,')');
167
+ else if length ne 8 then typ='num length='!!cats(length);
168
+ else typ='num';
169
+ put name typ fmt notnul lab;
170
+ run;
171
+
172
+ /* Extra step for data constraints */
173
+ %addConst()
174
+
175
+ data _null_;
176
+ file &fref mod;
177
+ put ');';
178
+ run;
179
+
180
+ /* Create Unique Indexes, but only if they were not already defined within
181
+ the Constraints section. */
182
+ data _null_;
183
+ *length ds $128;
184
+ set &idxinfo(
185
+ where=(
186
+ memname="&curds"
187
+ and unique='yes'
188
+ and indxname not in (
189
+ %sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
190
+ )
191
+ )
192
+ );
193
+ file &fref mod;
194
+ by idxusage indxname;
195
+ /* ds=cats(libname,'.',memname); */
196
+ if first.indxname then do;
197
+ put 'CREATE UNIQUE INDEX ' indxname "ON &libref..&curds (" ;
198
+ put ' ' name ;
199
+ end;
200
+ else put ' ,' name ;
201
+ *else put ' ,' name ;
202
+ if last.indxname then do;
203
+ put ');';
204
+ end;
205
+ run;
206
+
207
+ /*
208
+ ods output IntegrityConstraints=ic;
209
+ proc contents data=testali out2=info;
210
+ run;
211
+ */
212
+ %end;
213
+ %end;
214
+ %else %if &flavour=TSQL %then %do;
215
+ /* if schema does not exist, set to be same as libref */
216
+ %local schemaactual;
217
+ proc sql noprint;
218
+ select sysvalue into: schemaactual
219
+ from dictionary.libnames
220
+ where upcase(libname)="&libref" and engine='SQLSVR';
221
+ %let schema=%sysfunc(coalescec(&schemaactual,&schema,&libref));
222
+
223
+ %do x=1 %to %sysfunc(countw(&dsnlist));
224
+ %let curds=%scan(&dsnlist,&x);
225
+ data _null_;
226
+ file &fref mod;
227
+ put "/* TSQL Flavour DDL for &schema..&curds */";
228
+ data _null_;
229
+ file &fref mod;
230
+ set &colinfo (where=(upcase(memname)="&curds")) end=last;
231
+ if _n_=1 then do;
232
+ if memtype='DATA' then do;
233
+ put "create table [&schema].[&curds](";
234
+ end;
235
+ else do;
236
+ /* just a placeholder - we filter out views at the top */
237
+ put "create view [&schema].[&curds](";
238
+ end;
239
+ put " "@@;
240
+ end;
241
+ else put " ,"@@;
242
+ format=upcase(format);
243
+ if 1=0 then; /* dummy if */
244
+ %if &applydttm=YES %then %do;
245
+ else if format=:'DATETIME' then fmt='[datetime2](7) ';
246
+ %end;
247
+ else if type='num' then fmt='[decimal](18,2)';
248
+ else if length le 8000 then fmt='[varchar]('!!cats(length)!!')';
249
+ else fmt=cats('[varchar](max)');
250
+ if notnull='yes' then notnul=' NOT NULL';
251
+ put "[" name +(-1) "]" fmt notnul;
252
+ run;
253
+
254
+ /* Extra step for data constraints */
255
+ %addConst()
256
+
257
+ /* Create Unique Indexes, but only if they were not already defined within
258
+ the Constraints section. */
259
+ data _null_;
260
+ *length ds $128;
261
+ set &idxinfo(
262
+ where=(
263
+ memname="&curds"
264
+ and unique='yes'
265
+ and indxname not in (
266
+ %sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
267
+ )
268
+ )
269
+ );
270
+ file &fref mod;
271
+ by idxusage indxname;
272
+ *ds=cats(libname,'.',memname);
273
+ if first.indxname then do;
274
+ /* add nonclustered in case of multiple unique indexes */
275
+ put ' ,index [' indxname +(-1) '] UNIQUE NONCLUSTERED (';
276
+ put ' [' name +(-1) ']';
277
+ end;
278
+ else put ' ,[' name +(-1) ']';
279
+ if last.indxname then do;
280
+ put ' )';
281
+ end;
282
+ run;
283
+
284
+ data _null_;
285
+ file &fref mod;
286
+ put ')';
287
+ put 'GO';
288
+ run;
289
+
290
+ /* add extended properties for labels */
291
+ data _null_;
292
+ file &fref mod;
293
+ length nm $64 lab $1024;
294
+ set &colinfo (where=(upcase(memname)="&curds" and label ne '')) end=last;
295
+ nm=cats("N'",tranwrd(name,"'","''"),"'");
296
+ lab=cats("N'",tranwrd(label,"'","''"),"'");
297
+ put ' ';
298
+ put "EXEC sys.sp_addextendedproperty ";
299
+ put " @name=N'MS_Description',@value=" lab ;
300
+ put " ,@level0type=N'SCHEMA',@level0name=N'&schema' ";
301
+ put " ,@level1type=N'TABLE',@level1name=N'&curds'";
302
+ put " ,@level2type=N'COLUMN',@level2name=" nm ;
303
+ if last then put 'GO';
304
+ run;
305
+ %end;
306
+ %end;
307
+ %else %if &flavour=PGSQL %then %do;
308
+ /* if schema does not exist, set to be same as libref */
309
+ %local schemaactual;
310
+ proc sql noprint;
311
+ select sysvalue into: schemaactual
312
+ from dictionary.libnames
313
+ where upcase(libname)="&libref" and engine='POSTGRES';
314
+ %let schema=%sysfunc(coalescec(&schemaactual,&schema,&libref));
315
+ data _null_;
316
+ file &fref mod;
317
+ put "CREATE SCHEMA &schema;";
318
+ %do x=1 %to %sysfunc(countw(&dsnlist));
319
+ %let curds=%scan(&dsnlist,&x);
320
+ %local curdsvarcount;
321
+ %let curdsvarcount=%mf_getvarcount(&libref..&curds);
322
+ %if &curdsvarcount>1600 %then %do;
323
+ data _null_;
324
+ file &fref mod;
325
+ put "/* &libref..&curds contains &curdsvarcount vars */";
326
+ put "/* Postgres cannot create tables with over 1600 vars */";
327
+ put "/* No DDL will be generated for this table";
328
+ run;
329
+ %end;
330
+ %else %do;
331
+ data _null_;
332
+ file &fref mod;
333
+ put "/* Postgres Flavour DDL for &schema..&curds */";
334
+ data _null_;
335
+ file &fref mod;
336
+ set &colinfo (where=(upcase(memname)="&curds")) end=last;
337
+ length fmt $32;
338
+ if _n_=1 then do;
339
+ if memtype='DATA' then do;
340
+ put "CREATE TABLE &schema..&curds (";
341
+ end;
342
+ else do;
343
+ /* just a placeholder - we filter out views at the top */
344
+ put "CREATE VIEW &schema..&curds (";
345
+ end;
346
+ put " "@@;
347
+ end;
348
+ else put " ,"@@;
349
+ format=upcase(format);
350
+ if 1=0 then; /* dummy if */
351
+ %if &applydttm=YES %then %do;
352
+ else if format=:'DATETIME' then fmt=' TIMESTAMP ';
353
+ %end;
354
+ else if type='num' then fmt=' DOUBLE PRECISION';
355
+ else fmt='VARCHAR('!!cats(length)!!')';
356
+ if notnull='yes' then notnul=' NOT NULL';
357
+ /* quote column names in case they represent reserved words */
358
+ name2=quote(trim(name));
359
+ put name2 fmt notnul;
360
+ run;
361
+
362
+ /* Extra step for data constraints */
363
+ %addConst()
364
+
365
+ data _null_;
366
+ file &fref mod;
367
+ put ');';
368
+ run;
369
+
370
+ /* Create Unique Indexes, but only if they were not already defined within
371
+ the Constraints section. */
372
+ data _null_;
373
+ *length ds $128;
374
+ set &idxinfo(
375
+ where=(
376
+ memname="&curds"
377
+ and unique='yes'
378
+ and indxname not in (
379
+ %sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
380
+ )
381
+ )
382
+ );
383
+ file &fref mod;
384
+ by idxusage indxname;
385
+ if first.indxname then do;
386
+ put 'CREATE UNIQUE INDEX "' indxname +(-1) '" ' "ON &schema..&curds(";
387
+ put ' "' name +(-1) '"' ;
388
+ end;
389
+ else put ' ,"' name +(-1) '"';
390
+ if last.indxname then do;
391
+ put ');';
392
+ end;
393
+ run;
394
+ %end;
395
+ %end;
396
+ %end;
397
+ %if %upcase(&showlog)=YES %then %do;
398
+ options ps=max;
399
+ data _null_;
400
+ infile &fref;
401
+ input;
402
+ putlog _infile_;
403
+ run;
404
+ %end;
41
405
 
42
406
  %mend mp_ds2ddl;
@@ -56,7 +56,7 @@
56
56
  @li mp_dsmeta.test.sas
57
57
  @li mp_getcols.sas
58
58
  @li mp_getdbml.sas
59
- @li mp_getddl.sas
59
+ @li mp_ds2ddl.sas
60
60
  @li mp_getformats.sas
61
61
  @li mp_getpk.sas
62
62
  @li mp_guesspk.sas
@@ -23,7 +23,7 @@
23
23
  |AND|AND|1|SOME_TIME|=|77333|
24
24
  @param [in] filter_summary= (PERM.FILTER_SUMMARY) Permanent table containing
25
25
  summary filter values. The definition is available by running
26
- mp_coretable.sas as follows: `mp_coretable(FILTER_SUMMARY)`. Example
26
+ mddl_dc_filtersummary.sas as follows: `%mddl_dc_filtersummary()`. Example
27
27
  values:
28
28
  |FILTER_RK:best.|FILTER_HASH:$32.|FILTER_TABLE:$41.|PROCESSED_DTTM:datetime19.|
29
29
  |---|---|---|---|
@@ -32,7 +32,7 @@
32
32
  |`3 `|`8048BD908DBBD83D013560734E90D394 `|`VIYA6014.MPE_TABLES `|`1956093620.6`|
33
33
  @param [in] filter_detail= (PERM.FILTER_DETAIL) Permanent table containing
34
34
  detailed (raw) filter values. The definition is available by running
35
- mp_coretable.sas as follows: `mp_coretable(FILTER_DETAIL)`. Example
35
+ mddl_dc_filterdetail.sas as follows: `%mddl_dc_filterdetail()`. Example
36
36
  values:
37
37
  |FILTER_HASH:$32.|FILTER_LINE:best.|GROUP_LOGIC:$3.|SUBGROUP_LOGIC:$3.|SUBGROUP_ID:best.|VARIABLE_NM:$32.|OPERATOR_NM:$12.|RAW_VALUE:$4000.|PROCESSED_DTTM:datetime19.|
38
38
  |---|---|---|---|---|---|---|---|---|
@@ -41,7 +41,7 @@
41
41
  |`87737DB9EEE2650F5C89956CEAD0A14F `|`1 `|`AND `|`AND `|`1 `|`PRIMARY_KEY_FIELD `|`IN `|`(1,2,3) `|`1956084451.9 `|
42
42
  @param [in] lock_table= (PERM.LOCK_TABLE) Permanent locking table. Used to
43
43
  manage concurrent access. The definition is available by running
44
- mp_coretable.sas as follows: `mp_coretable(LOCKTABLE)`.
44
+ mddl_dc_locktable.sas as follows: `%mddl_dc_locktable()`.
45
45
  @param [in] maxkeytable= (0) Optional permanent reference table used for
46
46
  retained key tracking. Described in mp_retainedkey.sas.
47
47
  @param [in] mdebug= (1) set to 1 to enable DEBUG messages
@@ -68,7 +68,7 @@
68
68
 
69
69
  %if &num2char=NO %then %do;
70
70
  /* compile length function for numeric fields */
71
- %mcf_length(wrap=YES, insert_cmplib=YES)
71
+ %mcf_length()
72
72
  %end;
73
73
 
74
74
  %if &num2char=NO
@@ -331,7 +331,8 @@
331
331
  prxchange('s/\\/\\\\/',-1,&&name&i)
332
332
  )))))))))))))!!'"';
333
333
  end;
334
- else &&name&i=quote(cats(&&name&i));
334
+ /* trim (not cats) so leading blanks are retained */
335
+ else &&name&i='"'!!trim(&&name&i)!!'"';
335
336
  %end;
336
337
  %end;
337
338
  run;
@@ -5,7 +5,7 @@
5
5
  macro.
6
6
  Usage:
7
7
 
8
- %mp_getddl(sashelp, schema=work, fref=tempref)
8
+ %mp_ds2ddl(sashelp, schema=work, fref=tempref)
9
9
 
10
10
  %mp_lib2inserts(sashelp, schema=work, outref=tempref)
11
11
 
@@ -24,11 +24,11 @@
24
24
  @li permlib.base_table - the target table to be loaded (**not** loaded by this
25
25
  macro)
26
26
  @li permlib.maxkeytable - optional, used to store load metaadata.
27
- The definition is available by running mp_coretable.sas as follows:
28
- `mp_coretable(MAXKEYTABLE)`.
27
+ The definition is available in mddl_dc_maxkeytable.sas as follows:
28
+ `%mddl_dc_maxkeytable()`.
29
29
  @li permlib.locktable - Necessary if maxkeytable is being populated. The
30
- definition is available by running mp_coretable.sas as follows:
31
- `mp_coretable(LOCKTABLE)`.
30
+ definition is available in mddl_dc_locktable.sas as follows:
31
+ `%mddl_dc_locktable()`.
32
32
 
33
33
 
34
34
  @param [in] base_lib= (WORK) Libref of the base (target) table.
@@ -13,7 +13,7 @@
13
13
 
14
14
  In both cases, it is necessary that the transactions are stored using
15
15
  the mp_storediffs.sas macro, or at least that the underlying table is
16
- structured as per the definition in mp_coretable.sas (DIFFTABLE entry)
16
+ structured as per the definition in mddl_dc_difftable.sas
17
17
 
18
18
  <b>This</b> macro is used to convert the stored changes (tall format) into
19
19
  staged changes (wide format), with base table values incorporated (in the
@@ -166,7 +166,7 @@
166
166
  in libref.dataset format.
167
167
  @param [in] auditlibds Dataset with previously applied transactions, to be
168
168
  re-applied. Use libref.dataset format.
169
- DDL as follows: %mp_coretable(DIFFTABLE)
169
+ DDL as follows: %mddl_dc_difftable()
170
170
  @param [in] key Space seperated list of key variables
171
171
  @param [in] mdebug= Set to 1 to enable DEBUG messages and preserve outputs
172
172
  @param [in] processed_dttm_var= (0) If a variable is being used to mark
@@ -194,7 +194,7 @@
194
194
  @li mp_ds2squeeze.sas
195
195
 
196
196
  <h4> Related Macros </h4>
197
- @li mp_coretable.sas
197
+ @li mddl_dc_difftable.sas
198
198
  @li mp_stackdiffs.test.sas
199
199
  @li mp_storediffs.sas
200
200
  @li mp_stripdiffs.sas
@@ -48,7 +48,7 @@
48
48
  @param [in] appds= (0) Dataset with appended records
49
49
  @param [in] modds= (0) Dataset with modified records
50
50
  @param [out] outds= (work.mp_storediffs) Output table containing stored data.
51
- DDL as follows: %mp_coretable(DIFFTABLE)
51
+ DDL as follows: %mddl_dc_difftable()
52
52
 
53
53
  @param [in] processed_dttm= (0) Provide a datetime constant in relation to
54
54
  the actual load time. If not provided, current timestamp is used.
@@ -28,6 +28,9 @@
28
28
  @param [in] rule The rule to apply. Current rules:
29
29
  @li ISINT - checks if the variable is an integer
30
30
  @li ISLIB - checks if the value is a valid libref (NOT whether it exists)
31
+ @li ISNAME - checks if the value is a valid SAS NAME (V7 rules - up to 32
32
+ chars, starting with a letter or underscore, followed by letters,
33
+ numbers or underscores)
31
34
  @li ISNUM - checks if the variable is numeric
32
35
  @li LIBDS - matches LIBREF.DATASET format
33
36
  @li FORMAT - checks if the provided format is syntactically valid
@@ -79,6 +82,20 @@
79
82
  if prxmatch(&tempcol, trim(&incol)) then &outcol=1;
80
83
  else &outcol=0;
81
84
  %end;
85
+ %else %if &rule=ISNAME %then %do;
86
+ /* match a valid SAS name (V7 rules) */
87
+ if _n_=1 then do;
88
+ retain &tempcol;
89
+ &tempcol=prxparse('/^[_a-z]\w{0,31}$/i');
90
+ if missing(&tempcol) then do;
91
+ putlog 'ERR' +(-1) "OR: Invalid expression for ISNAME";
92
+ stop;
93
+ end;
94
+ drop &tempcol;
95
+ end;
96
+ if prxmatch(&tempcol, trim(&incol)) then &outcol=1;
97
+ else &outcol=0;
98
+ %end;
82
99
  %else %if &rule=LIBDS %then %do;
83
100
  /* match libref.dataset */
84
101
  if _n_=1 then do;
@@ -94,10 +111,10 @@
94
111
  else &outcol=0;
95
112
  %end;
96
113
  %else %if &rule=FORMAT %then %do;
97
- /* match valid format - regex could probably be improved */
114
+ /* match valid SAS format*/
98
115
  if _n_=1 then do;
99
116
  retain &tempcol;
100
- &tempcol=prxparse('/^[_a-z\$]\w{0,31}\.[0-9]*$/i');
117
+ &tempcol=prxparse('/^(?:[_a-z\$]\w{0,31}|[0-9]+)\.[0-9]*$/i');
101
118
  if missing(&tempcol) then do;
102
119
  putlog 'ERR' +(-1) "OR: Invalid expression for FORMAT";
103
120
  stop;
package/package.json CHANGED
@@ -39,7 +39,6 @@
39
39
  "test": "jest --config=jest.config.js --coverage",
40
40
  "lint:fix": "npx prettier --write \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
41
41
  "lint": "npx prettier --check \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
42
- "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true",
43
42
  "semantic-release": "semantic-release"
44
43
  },
45
44
  "repository": {
@@ -53,34 +52,30 @@
53
52
  },
54
53
  "homepage": "https://github.com/sasjs/utils#readme",
55
54
  "devDependencies": {
56
- "@sasjs/core": "4.68.1",
55
+ "@sasjs/core": "5.3.0",
57
56
  "@semantic-release/exec": "6.0.3",
58
57
  "@semantic-release/git": "10.0.1",
59
- "@types/cli-table": "0.3.0",
60
- "@types/find": "0.2.1",
58
+ "@types/cli-table": "0.3.4",
61
59
  "@types/jest": "29.4.0",
62
- "@types/valid-url": "1.0.3",
60
+ "@types/prompts": "2.4.9",
63
61
  "babel-jest": "29.4.3",
64
62
  "jest": "29.4.3",
65
63
  "jest-extended": "3.2.4",
66
- "semantic-release": "25.0.8",
67
- "ts-jest": "29.0.5",
68
- "ts-loader": "9.2.6",
69
- "ts-node": "10.9.1",
64
+ "semantic-release": "25.0.9",
65
+ "ts-jest": "29.4.14",
66
+ "ts-loader": "9.6.2",
67
+ "ts-node": "10.9.2",
70
68
  "typescript": "4.5.4"
71
69
  },
72
70
  "dependencies": {
73
71
  "@fast-csv/format": "4.3.5",
74
72
  "@types/fs-extra": "11.0.4",
75
- "@types/prompts": "2.0.13",
76
73
  "chalk": "4.1.1",
77
- "cli-table": "0.3.6",
78
- "consola": "2.15.0",
79
- "find": "0.3.0",
80
- "fs-extra": "11.3.0",
74
+ "cli-table": "0.3.11",
75
+ "consola": "3.4.2",
76
+ "fs-extra": "11.4.1",
81
77
  "jwt-decode": "3.1.2",
82
- "prompts": "2.4.1",
83
- "valid-url": "1.0.9"
78
+ "prompts": "2.4.2"
84
79
  },
85
- "version": "3.6.1"
80
+ "version": "3.6.3"
86
81
  }
@@ -8,15 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
12
  exports.getDeprecatedHeader = exports.getDependencies = exports.getDepInfo = exports.DependencyHeader = exports.DependencyType = void 0;
16
13
  const utils_1 = require("../utils");
17
14
  const _1 = require("./");
18
15
  const utils_2 = require("../utils");
19
- const find_1 = __importDefault(require("find"));
20
16
  const file_1 = require("../file");
21
17
  const formatter_1 = require("../formatter");
22
18
  // REFACTOR: move logic supporting SAS Macros dependencies to this file
@@ -68,7 +64,7 @@ const getDependencies = (fileName, fileContent, folders, depType, compileTree) =
68
64
  const foundDepsNames = [];
69
65
  yield (0, utils_2.asyncForEach)(folders, (folder) => __awaiter(void 0, void 0, void 0, function* () {
70
66
  yield (0, utils_2.asyncForEach)(uniqDeps, (dep) => __awaiter(void 0, void 0, void 0, function* () {
71
- const filePaths = find_1.default.fileSync(dep.fileName, folder);
67
+ const filePaths = (0, file_1.findFilesByName)(dep.fileName, folder);
72
68
  if (filePaths.length) {
73
69
  let encodedFileContent = '';
74
70
  if (compileTree &&