@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.
- package/.github/workflows/dependency-staleness.yml +46 -0
- package/.github/workflows/publish.yml +20 -1
- package/.github/workflows/run-tests-windows.yml +6 -3
- package/.github/workflows/run-tests.yml +9 -3
- package/auth/auth.js +2 -5
- package/auth/auth.js.map +1 -1
- package/file/file.d.ts +6 -0
- package/file/file.js +28 -1
- package/file/file.js.map +1 -1
- package/file/index.d.ts +1 -1
- package/file/index.js +2 -1
- package/file/index.js.map +1 -1
- package/input/validators.js +2 -8
- package/input/validators.js.map +1 -1
- package/logger/logger.js +8 -8
- package/logger/logger.js.map +1 -1
- package/macros/mf_getuniquelibref.sas +2 -4
- package/macros/mf_getvalue.sas +24 -9
- package/macros/mp_abort.sas +8 -2
- package/macros/mp_assert.sas +2 -2
- package/macros/mp_assertcols.sas +6 -4
- package/macros/mp_assertcolvals.sas +2 -2
- package/macros/mp_assertdsobs.sas +2 -2
- package/macros/mp_assertscope.sas +2 -2
- package/macros/mp_ds2csv.sas +2 -2
- package/macros/mp_ds2ddl.sas +388 -24
- package/macros/mp_dsmeta.sas +1 -1
- package/macros/mp_filterstore.sas +3 -3
- package/macros/mp_getmaxvarlengths.sas +1 -1
- package/macros/mp_jsonout.sas +2 -1
- package/macros/mp_lib2inserts.sas +1 -1
- package/macros/mp_retainedkey.sas +4 -4
- package/macros/mp_stackdiffs.sas +3 -3
- package/macros/mp_storediffs.sas +1 -1
- package/macros/mp_validatecol.sas +19 -2
- package/package.json +12 -17
- package/sasjsCli/getDependencies.js +1 -5
- package/sasjsCli/getDependencies.js.map +1 -1
- package/sasjsCli/getDependencyPaths.js +1 -5
- package/sasjsCli/getDependencyPaths.js.map +1 -1
- package/types/targetValidators.js +4 -9
- package/types/targetValidators.js.map +1 -1
- package/utils/index.d.ts +1 -1
- package/utils/index.js +3 -1
- package/utils/index.js.map +1 -1
- package/utils/url.d.ts +2 -0
- package/utils/url.js +14 -1
- package/utils/url.js.map +1 -1
- package/.github/dependabot.yml +0 -7
- package/.github/workflows/dependabot-auto-approve.yml +0 -21
- package/.github/workflows/dependabot-auto-merge.yml +0 -23
- package/macros/mp_coretable.sas +0 -73
- package/macros/mp_getddl.sas +0 -405
- package/macros/mp_testservice.sas +0 -39
package/macros/mp_ds2ddl.sas
CHANGED
|
@@ -1,42 +1,406 @@
|
|
|
1
1
|
/**
|
|
2
|
-
@file
|
|
3
|
-
@brief
|
|
4
|
-
@details
|
|
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
|
-
|
|
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= (
|
|
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
|
|
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(
|
|
45
|
+
%macro mp_ds2ddl(libref,ds,fref=getddl,flavour=SAS,showlog=YES,schema=
|
|
25
46
|
,applydttm=NO
|
|
26
47
|
)/*/STORE SOURCE*/;
|
|
27
48
|
|
|
28
|
-
|
|
29
|
-
%
|
|
30
|
-
|
|
31
|
-
%
|
|
32
|
-
|
|
33
|
-
%
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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;
|
package/macros/mp_dsmeta.sas
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
package/macros/mp_jsonout.sas
CHANGED
|
@@ -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
|
|
28
|
-
|
|
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
|
|
31
|
-
|
|
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.
|
package/macros/mp_stackdiffs.sas
CHANGED
|
@@ -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
|
|
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: %
|
|
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
|
|
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
|
package/macros/mp_storediffs.sas
CHANGED
|
@@ -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: %
|
|
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
|
|
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": "
|
|
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.
|
|
60
|
-
"@types/find": "0.2.1",
|
|
58
|
+
"@types/cli-table": "0.3.4",
|
|
61
59
|
"@types/jest": "29.4.0",
|
|
62
|
-
"@types/
|
|
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.
|
|
67
|
-
"ts-jest": "29.
|
|
68
|
-
"ts-loader": "9.2
|
|
69
|
-
"ts-node": "10.9.
|
|
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.
|
|
78
|
-
"consola": "
|
|
79
|
-
"
|
|
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.
|
|
83
|
-
"valid-url": "1.0.9"
|
|
78
|
+
"prompts": "2.4.2"
|
|
84
79
|
},
|
|
85
|
-
"version": "3.6.
|
|
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 =
|
|
67
|
+
const filePaths = (0, file_1.findFilesByName)(dep.fileName, folder);
|
|
72
68
|
if (filePaths.length) {
|
|
73
69
|
let encodedFileContent = '';
|
|
74
70
|
if (compileTree &&
|