@sasjs/utils 3.5.1 → 3.5.2
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/file/file.js +4 -2
- package/file/file.js.map +1 -1
- package/macros/mf_abort.sas +7 -2
- package/macros/mf_deletefile.sas +1 -1
- package/macros/mf_existds.sas +1 -1
- package/macros/mf_existfileref.sas +2 -2
- package/macros/mf_existfunction.sas +1 -1
- package/macros/mf_existvar.sas +8 -4
- package/macros/mf_existvarlist.sas +2 -2
- package/macros/mf_getapploc.sas +1 -0
- package/macros/mf_getattrc.sas +2 -2
- package/macros/mf_getattrn.sas +2 -2
- package/macros/mf_getfmtlist.sas +3 -4
- package/macros/mf_getgitbranch.sas +37 -0
- package/macros/mf_getkeyvalue.sas +3 -2
- package/macros/mf_getplatform.sas +1 -1
- package/macros/mf_getschema.sas +1 -1
- package/macros/mf_getuniquelibref.sas +1 -1
- package/macros/mf_getuniquename.sas +1 -1
- package/macros/mf_getuser.sas +0 -2
- package/macros/mf_getvalue.sas +3 -3
- package/macros/mf_getvarformat.sas +2 -1
- package/macros/mf_getvarlen.sas +2 -2
- package/macros/mf_getvarnum.sas +2 -2
- package/macros/mf_getvartype.sas +2 -2
- package/macros/mf_getxengine.sas +1 -1
- package/macros/mf_increment.sas +2 -2
- package/macros/mf_isblank.sas +2 -2
- package/macros/mf_isdir.sas +1 -1
- package/macros/mf_loc.sas +6 -1
- package/macros/mf_mkdir.sas +1 -1
- package/macros/mf_mval.sas +2 -0
- package/macros/mf_nobs.sas +1 -1
- package/macros/mf_readfile.sas +63 -0
- package/macros/mf_trimstr.sas +2 -2
- package/macros/mf_wordsinstr1andstr2.sas +2 -2
- package/macros/mf_wordsinstr1butnotstr2.sas +2 -2
- package/macros/mf_writefile.sas +2 -2
- package/macros/mp_abort.sas +50 -13
- package/macros/mp_aligndecimal.sas +95 -0
- package/macros/mp_appendfile.sas +2 -2
- package/macros/mp_applyformats.sas +5 -5
- package/macros/mp_assert.sas +1 -1
- package/macros/mp_assertcols.sas +3 -3
- package/macros/mp_assertcolvals.sas +9 -5
- package/macros/mp_base64copy.sas +2 -2
- package/macros/mp_binarycopy.sas +7 -6
- package/macros/mp_chop.sas +4 -3
- package/macros/mp_cleancsv.sas +5 -4
- package/macros/mp_cntlout.sas +16 -7
- package/macros/mp_copyfolder.sas +2 -2
- package/macros/mp_createconstraints.sas +3 -3
- package/macros/mp_createwebservice.sas +1 -1
- package/macros/mp_csv2ds.sas +6 -5
- package/macros/mp_deleteconstraints.sas +5 -3
- package/macros/mp_deletefolder.sas +1 -1
- package/macros/mp_dictionary.sas +1 -1
- package/macros/mp_dirlist.sas +1 -1
- package/macros/mp_distinctfmtvalues.sas +5 -5
- package/macros/mp_ds2csv.sas +10 -1
- package/macros/mp_ds2ddl.sas +14 -2
- package/macros/mp_ds2md.sas +1 -0
- package/macros/mp_dsmeta.sas +2 -2
- package/macros/mp_filtercheck.sas +105 -16
- package/macros/mp_filtergenerate.sas +2 -2
- package/macros/mp_filterstore.sas +4 -3
- package/macros/mp_getcols.sas +3 -2
- package/macros/mp_getdbml.sas +4 -4
- package/macros/mp_getddl.sas +15 -10
- package/macros/mp_getformats.sas +13 -3
- package/macros/mp_gitlog.sas +104 -0
- package/macros/mp_gitstatus.sas +1 -1
- package/macros/mp_gsubfile.sas +6 -6
- package/macros/mp_guesspk.sas +1 -1
- package/macros/mp_hashdataset.sas +1 -1
- package/macros/mp_init.sas +1 -0
- package/macros/mp_lib2cards.sas +7 -7
- package/macros/mp_loadformat.sas +127 -47
- package/macros/mp_lockanytable.sas +31 -24
- package/macros/mp_md5.sas +3 -4
- package/macros/mp_perflog.sas +3 -3
- package/macros/mp_prevobs.sas +5 -5
- package/macros/mp_recursivejoin.sas +7 -6
- package/macros/mp_replace.sas +5 -4
- package/macros/mp_runddl.sas +3 -3
- package/macros/mp_searchcols.sas +7 -6
- package/macros/mp_stackdiffs.sas +1 -0
- package/macros/mp_storediffs.sas +8 -8
- package/macros/mp_stprequests.sas +4 -3
- package/macros/mp_stripdiffs.sas +255 -0
- package/macros/mp_testjob.sas +2 -2
- package/macros/mp_testwritespeedlibrary.sas +3 -3
- package/macros/mp_tree.sas +2 -2
- package/macros/mp_unzip.sas +5 -4
- package/macros/mp_updatevarlength.sas +3 -3
- package/macros/mp_validatecol.sas +3 -3
- package/macros/mp_wait4file.sas +1 -1
- package/macros/mp_webin.sas +1 -1
- package/macros/mp_zip.sas +5 -5
- package/package.json +5 -6
package/macros/mp_loadformat.sas
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
format, to prevent loss of data - UNLESS the input dataset contains a marker
|
|
10
10
|
column, specifying that a particular row needs to be deleted (`delete_col=`).
|
|
11
11
|
|
|
12
|
+
Positions of formats are made using the FMTROW variable - this must be present
|
|
13
|
+
and unique (on TYPE / FMTNAME / FMTROW).
|
|
14
|
+
|
|
12
15
|
This macro can also be used to identify which records would be (or were)
|
|
13
16
|
considered new, modified or deleted (`loadtarget=`) by creating the following
|
|
14
17
|
tables:
|
|
@@ -17,7 +20,7 @@
|
|
|
17
20
|
@li work.outds_del
|
|
18
21
|
@li work.outds_mod
|
|
19
22
|
|
|
20
|
-
For example usage, see
|
|
23
|
+
For example usage, see test (under Related Macros)
|
|
21
24
|
|
|
22
25
|
@param [in] libcat The format catalog to be loaded
|
|
23
26
|
@param [in] libds The staging table to load
|
|
@@ -34,18 +37,22 @@
|
|
|
34
37
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages and preserve outputs
|
|
35
38
|
|
|
36
39
|
<h4> SAS Macros </h4>
|
|
37
|
-
@li
|
|
40
|
+
@li mf_existds.sas
|
|
41
|
+
@li mf_existvar.sas
|
|
38
42
|
@li mf_getuniquename.sas
|
|
39
43
|
@li mf_nobs.sas
|
|
40
44
|
@li mp_abort.sas
|
|
45
|
+
@li mp_aligndecimal.sas
|
|
41
46
|
@li mp_cntlout.sas
|
|
42
47
|
@li mp_lockanytable.sas
|
|
48
|
+
@li mp_md5.sas
|
|
43
49
|
@li mp_storediffs.sas
|
|
44
50
|
|
|
45
51
|
<h4> Related Macros </h4>
|
|
46
52
|
@li mddl_dc_difftable.sas
|
|
47
53
|
@li mddl_dc_locktable.sas
|
|
48
|
-
@li mp_loadformat.test.sas
|
|
54
|
+
@li mp_loadformat.test.1.sas
|
|
55
|
+
@li mp_loadformat.test.2.sas
|
|
49
56
|
@li mp_lockanytable.sas
|
|
50
57
|
@li mp_stackdiffs.sas
|
|
51
58
|
|
|
@@ -67,7 +74,7 @@
|
|
|
67
74
|
);
|
|
68
75
|
/* set up local macro variables and temporary tables (with a prefix) */
|
|
69
76
|
%local err msg prefix dslist i var fmtlist ibufsize;
|
|
70
|
-
%let dslist=base_fmts template inlibds ds1 stagedata storediffs;
|
|
77
|
+
%let dslist=base_fmts template inlibds ds1 stagedata storediffs del1 del2;
|
|
71
78
|
%if &outds_add=0 %then %let dslist=&dslist outds_add;
|
|
72
79
|
%if &outds_del=0 %then %let dslist=&dslist outds_del;
|
|
73
80
|
%if &outds_mod=0 %then %let dslist=&dslist outds_mod;
|
|
@@ -78,17 +85,20 @@
|
|
|
78
85
|
%let &var=%upcase(&prefix._&var);
|
|
79
86
|
%end;
|
|
80
87
|
|
|
81
|
-
/*
|
|
82
|
-
format values can be up to 32767 wide. SQL joins on such a wide column can
|
|
83
|
-
cause buffer issues. Update ibufsize and reset at the end.
|
|
84
|
-
*/
|
|
85
|
-
%let ibufsize=%sysfunc(getoption(ibufsize));
|
|
86
|
-
options ibufsize=32767 ;
|
|
87
|
-
|
|
88
88
|
/* in DC, format catalogs maybe specified in the libds with a -FC extension */
|
|
89
89
|
%let libcat=%scan(&libcat,1,-);
|
|
90
90
|
|
|
91
91
|
/* perform input validations */
|
|
92
|
+
%mp_abort(
|
|
93
|
+
iftrue=(%mf_existds(&libds)=0)
|
|
94
|
+
,mac=&sysmacroname
|
|
95
|
+
,msg=%str(&libds could not be found)
|
|
96
|
+
)
|
|
97
|
+
%mp_abort(
|
|
98
|
+
iftrue=(%mf_existvar(&libds,FMTROW)=0)
|
|
99
|
+
,mac=&sysmacroname
|
|
100
|
+
,msg=%str(FMTROW not found in &libds)
|
|
101
|
+
)
|
|
92
102
|
%let err=0;
|
|
93
103
|
%let msg=0;
|
|
94
104
|
data _null_;
|
|
@@ -109,13 +119,6 @@ data _null_;
|
|
|
109
119
|
stop;
|
|
110
120
|
end;
|
|
111
121
|
end;
|
|
112
|
-
else if name='LIBDS' then do;
|
|
113
|
-
if exist(value) le 0 then do;
|
|
114
|
-
call symputx('msg',"Unable to open staging table: "!!value);
|
|
115
|
-
call symputx('err',1);
|
|
116
|
-
stop;
|
|
117
|
-
end;
|
|
118
|
-
end;
|
|
119
122
|
else if (name=:'OUTDS' or name in ('DELETE_COL','LOCKLIBDS','AUDITLIBDS'))
|
|
120
123
|
and missing(value) then do;
|
|
121
124
|
call symputx('msg',"missing value in var: "!!name);
|
|
@@ -123,6 +126,14 @@ data _null_;
|
|
|
123
126
|
stop;
|
|
124
127
|
end;
|
|
125
128
|
run;
|
|
129
|
+
data _null_;
|
|
130
|
+
set &libds;
|
|
131
|
+
if missing(fmtrow) then do;
|
|
132
|
+
call symputx('msg',"missing fmtrow in format: "!!FMTNAME);
|
|
133
|
+
call symputx('err',1);
|
|
134
|
+
stop;
|
|
135
|
+
end;
|
|
136
|
+
run;
|
|
126
137
|
|
|
127
138
|
%mp_abort(
|
|
128
139
|
iftrue=(&err ne 0)
|
|
@@ -130,33 +141,69 @@ run;
|
|
|
130
141
|
,msg=%str(&msg)
|
|
131
142
|
)
|
|
132
143
|
|
|
144
|
+
%local cnt;
|
|
145
|
+
proc sql noprint;
|
|
146
|
+
select count(distinct catx('|',type,fmtname,fmtrow)) into: cnt from &libds;
|
|
147
|
+
%mp_abort(
|
|
148
|
+
iftrue=(&cnt ne %mf_nobs(&libds))
|
|
149
|
+
,mac=&sysmacroname
|
|
150
|
+
,msg=%str(Non-unique primary key on &libds)
|
|
151
|
+
)
|
|
152
|
+
|
|
133
153
|
/**
|
|
134
154
|
* First, extract only relevant formats from the catalog
|
|
135
155
|
*/
|
|
136
156
|
proc sql noprint;
|
|
137
|
-
select distinct
|
|
157
|
+
select distinct
|
|
158
|
+
case
|
|
159
|
+
when type='N' then upcase(fmtname)
|
|
160
|
+
when type='C' then cats('$',upcase(fmtname))
|
|
161
|
+
when type='I' then cats('@',upcase(fmtname))
|
|
162
|
+
when type='J' then cats('@$',upcase(fmtname))
|
|
163
|
+
else "&sysmacroname:UNHANDLED"
|
|
164
|
+
end
|
|
165
|
+
into: fmtlist separated by ' '
|
|
166
|
+
from &libds;
|
|
138
167
|
|
|
139
168
|
%mp_cntlout(libcat=&libcat,fmtlist=&fmtlist,cntlout=&base_fmts)
|
|
140
169
|
|
|
170
|
+
/* get a hash of the row */
|
|
171
|
+
%local cvars nvars;
|
|
172
|
+
%let cvars=TYPE FMTNAME START END LABEL PREFIX FILL SEXCL EEXCL HLO DECSEP
|
|
173
|
+
DIG3SEP DATATYPE LANGUAGE;
|
|
174
|
+
%let nvars=FMTROW MIN MAX DEFAULT LENGTH FUZZ MULT NOEDIT;
|
|
175
|
+
data &base_fmts/note2err;
|
|
176
|
+
set &base_fmts;
|
|
177
|
+
fmthash=%mp_md5(cvars=&cvars, nvars=&nvars);
|
|
178
|
+
run;
|
|
141
179
|
|
|
142
180
|
/**
|
|
143
181
|
* Ensure input table and base_formats have consistent lengths and types
|
|
144
182
|
*/
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if 0 then set &template;
|
|
183
|
+
data &inlibds/nonote2err;
|
|
184
|
+
length &delete_col $3 FMTROW 8 start end label $32767;
|
|
185
|
+
if 0 then set &base_fmts;
|
|
149
186
|
set &libds;
|
|
187
|
+
by type fmtname notsorted;
|
|
150
188
|
if &delete_col='' then &delete_col='No';
|
|
151
189
|
fmtname=upcase(fmtname);
|
|
190
|
+
type=upcase(type);
|
|
152
191
|
if missing(type) then do;
|
|
153
|
-
if substr(fmtname,1,1)='
|
|
154
|
-
|
|
192
|
+
if substr(fmtname,1,1)='@' then do;
|
|
193
|
+
if substr(fmtname,2,1)='$' then type='J';
|
|
194
|
+
else type='I';
|
|
195
|
+
end;
|
|
196
|
+
else do;
|
|
197
|
+
if substr(fmtname,1,1)='$' then type='C';
|
|
198
|
+
else type='N';
|
|
199
|
+
end;
|
|
155
200
|
end;
|
|
156
|
-
if type
|
|
157
|
-
start=
|
|
158
|
-
end=
|
|
201
|
+
if type in ('N','I') then do;
|
|
202
|
+
%mp_aligndecimal(start,width=16)
|
|
203
|
+
%mp_aligndecimal(end,width=16)
|
|
159
204
|
end;
|
|
205
|
+
|
|
206
|
+
fmthash=%mp_md5(cvars=&cvars, nvars=&nvars);
|
|
160
207
|
run;
|
|
161
208
|
|
|
162
209
|
/**
|
|
@@ -167,11 +214,22 @@ create table &outds_add(drop=&delete_col) as
|
|
|
167
214
|
select a.*
|
|
168
215
|
from &inlibds a
|
|
169
216
|
left join &base_fmts b
|
|
170
|
-
on a.fmtname=b.fmtname
|
|
171
|
-
and a.start=b.start
|
|
217
|
+
on a.type=b.type and a.fmtname=b.fmtname and a.fmtrow=b.fmtrow
|
|
172
218
|
where b.fmtname is null
|
|
173
219
|
and upcase(a.&delete_col) ne "YES"
|
|
174
|
-
order by fmtname,
|
|
220
|
+
order by type, fmtname, fmtrow;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Identify modified records
|
|
224
|
+
*/
|
|
225
|
+
create table &outds_mod (drop=&delete_col) as
|
|
226
|
+
select a.*
|
|
227
|
+
from &inlibds a
|
|
228
|
+
inner join &base_fmts b
|
|
229
|
+
on a.type=b.type and a.fmtname=b.fmtname and a.fmtrow=b.fmtrow
|
|
230
|
+
where upcase(a.&delete_col) ne "YES"
|
|
231
|
+
and a.fmthash ne b.fmthash
|
|
232
|
+
order by type, fmtname, fmtrow;
|
|
175
233
|
|
|
176
234
|
/**
|
|
177
235
|
* Identify deleted records
|
|
@@ -180,24 +238,28 @@ create table &outds_del(drop=&delete_col) as
|
|
|
180
238
|
select a.*
|
|
181
239
|
from &inlibds a
|
|
182
240
|
inner join &base_fmts b
|
|
183
|
-
on a.fmtname=b.fmtname
|
|
184
|
-
and a.start=b.start
|
|
241
|
+
on a.type=b.type and a.fmtname=b.fmtname and a.fmtrow=b.fmtrow
|
|
185
242
|
where upcase(a.&delete_col)="YES"
|
|
186
|
-
order by fmtname,
|
|
243
|
+
order by type, fmtname, fmtrow;
|
|
187
244
|
|
|
188
245
|
/**
|
|
189
|
-
* Identify
|
|
246
|
+
* Identify fully deleted formats (where every record is removed)
|
|
247
|
+
* These require to be explicitly deleted in proc format
|
|
248
|
+
* del1 - identify _partial_ deletes
|
|
249
|
+
* del2 - exclude these, and also formats that come with _additions_
|
|
190
250
|
*/
|
|
191
|
-
create table &
|
|
251
|
+
create table &del1 as
|
|
192
252
|
select a.*
|
|
193
|
-
from &
|
|
194
|
-
|
|
195
|
-
on a.fmtname=b.fmtname
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
253
|
+
from &base_fmts a
|
|
254
|
+
left join &outds_del b
|
|
255
|
+
on a.type=b.type and a.fmtname=b.fmtname and a.fmtrow=b.fmtrow
|
|
256
|
+
where b.fmtrow is null;
|
|
257
|
+
|
|
258
|
+
create table &del2 as
|
|
259
|
+
select * from &outds_del
|
|
260
|
+
where cats(type,fmtname) not in (select cats(type,fmtname) from &outds_add)
|
|
261
|
+
and cats(type,fmtname) not in (select cats(type,fmtname) from &del1);
|
|
199
262
|
|
|
200
|
-
options ibufsize=&ibufsize;
|
|
201
263
|
|
|
202
264
|
%mp_abort(
|
|
203
265
|
iftrue=(&syscc ne 0)
|
|
@@ -206,19 +268,21 @@ options ibufsize=&ibufsize;
|
|
|
206
268
|
)
|
|
207
269
|
|
|
208
270
|
%if &loadtarget=YES %then %do;
|
|
271
|
+
/* new records plus base records that are not deleted or modified */
|
|
209
272
|
data &ds1;
|
|
210
273
|
merge &base_fmts(in=base)
|
|
211
274
|
&outds_mod(in=mod)
|
|
212
275
|
&outds_add(in=add)
|
|
213
276
|
&outds_del(in=del);
|
|
214
277
|
if not del and not mod;
|
|
215
|
-
by fmtname
|
|
278
|
+
by type fmtname fmtrow;
|
|
216
279
|
run;
|
|
280
|
+
/* add back the modified records */
|
|
217
281
|
data &stagedata;
|
|
218
282
|
set &ds1 &outds_mod;
|
|
219
283
|
run;
|
|
220
284
|
proc sort;
|
|
221
|
-
by fmtname
|
|
285
|
+
by type fmtname fmtrow;
|
|
222
286
|
run;
|
|
223
287
|
%end;
|
|
224
288
|
/* mp abort needs to run outside of conditional blocks */
|
|
@@ -228,7 +292,7 @@ options ibufsize=&ibufsize;
|
|
|
228
292
|
,msg=%str(SYSCC=&syscc prior to actual load)
|
|
229
293
|
)
|
|
230
294
|
%if &loadtarget=YES %then %do;
|
|
231
|
-
%if %mf_nobs(&stagedata)=0 %then %do;
|
|
295
|
+
%if %mf_nobs(&stagedata)=0 and %mf_nobs(&del2)=0 %then %do;
|
|
232
296
|
%put There are no changes to load in &libcat!;
|
|
233
297
|
%return;
|
|
234
298
|
%end;
|
|
@@ -244,6 +308,22 @@ options ibufsize=&ibufsize;
|
|
|
244
308
|
/* do the actual load */
|
|
245
309
|
proc format lib=&libcat cntlin=&stagedata;
|
|
246
310
|
run;
|
|
311
|
+
/* apply any full deletes */
|
|
312
|
+
%if %mf_nobs(&del2)>0 %then %do;
|
|
313
|
+
%local delfmtlist;
|
|
314
|
+
proc sql noprint;
|
|
315
|
+
select distinct case when type='N' then cats(fmtname,'.FORMAT')
|
|
316
|
+
when type='C' then cats(fmtname,'.FORMATC')
|
|
317
|
+
when type='J' then cats(fmtname,'.INFMTC')
|
|
318
|
+
when type='I' then cats(fmtname,'.INFMT')
|
|
319
|
+
else cats(fmtname,'.BADENTRY!!!') end
|
|
320
|
+
into: delfmtlist
|
|
321
|
+
separated by ' '
|
|
322
|
+
from &del2;
|
|
323
|
+
proc catalog catalog=&libcat;
|
|
324
|
+
delete &delfmtlist;
|
|
325
|
+
quit;
|
|
326
|
+
%end;
|
|
247
327
|
%if &locklibds ne 0 %then %do;
|
|
248
328
|
/* unlock the table */
|
|
249
329
|
%mp_lockanytable(UNLOCK
|
|
@@ -266,7 +346,7 @@ options ibufsize=&ibufsize;
|
|
|
266
346
|
|
|
267
347
|
%mp_storediffs(&libcat-FC
|
|
268
348
|
,&base_fmts
|
|
269
|
-
,FMTNAME
|
|
349
|
+
,TYPE FMTNAME FMTROW
|
|
270
350
|
,delds=&outds_del
|
|
271
351
|
,modds=&outds_mod
|
|
272
352
|
,appds=&outds_add
|
|
@@ -167,7 +167,7 @@ run;
|
|
|
167
167
|
data _null_;
|
|
168
168
|
putlog 'NOTE-' / 'NOTE-';
|
|
169
169
|
putlog "NOTE- &sysmacroname: table locked, waiting "@;
|
|
170
|
-
putlog "%sysfunc(sleep(&
|
|
170
|
+
putlog "%sysfunc(sleep(&loop_secs)) seconds.. ";
|
|
171
171
|
putlog "NOTE- (iteration &x of &loops)";
|
|
172
172
|
putlog 'NOTE-' / 'NOTE-';
|
|
173
173
|
run;
|
|
@@ -194,32 +194,39 @@ run;
|
|
|
194
194
|
%end;
|
|
195
195
|
%end;
|
|
196
196
|
%else %if &ACTION=UNLOCK %then %do;
|
|
197
|
-
%local status;
|
|
197
|
+
%local status cnt;
|
|
198
|
+
%let cnt=0;
|
|
198
199
|
proc sql noprint;
|
|
199
|
-
select
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
%if &syscc>0 %then %put syscc=&syscc sqlrc=&sqlrc;
|
|
203
|
-
%if &status=LOCKED %then %do;
|
|
204
|
-
data _null_;
|
|
205
|
-
putlog "&sysmacroname: unlocking &lib..&ds:";
|
|
206
|
-
run;
|
|
207
|
-
proc sql;
|
|
208
|
-
update &ctl_ds
|
|
209
|
-
set LOCK_STATUS_CD='UNLOCKED'
|
|
210
|
-
, LOCK_END_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
|
211
|
-
, LOCK_USER_NM="&user"
|
|
212
|
-
, LOCK_PID="&sysjobid"
|
|
213
|
-
, LOCK_REF="&ref"
|
|
214
|
-
where LOCK_LIB ="&lib" and LOCK_DS="&ds";
|
|
215
|
-
quit;
|
|
216
|
-
%end;
|
|
217
|
-
%else %if &status=UNLOCKED %then %do;
|
|
218
|
-
%put %str(WAR)NING: &lib..&ds is already unlocked!;
|
|
200
|
+
select count(*) into: cnt from &ctl_ds where LOCK_LIB ="&lib" & LOCK_DS="&ds";
|
|
201
|
+
%if &cnt=0 %then %do;
|
|
202
|
+
%put %str(WAR)NING: &lib..&ds was not previously locked in &ctl_ds!;
|
|
219
203
|
%end;
|
|
220
204
|
%else %do;
|
|
221
|
-
|
|
222
|
-
|
|
205
|
+
select LOCK_STATUS_CD into: status from &ctl_ds
|
|
206
|
+
where LOCK_LIB ="&lib" and LOCK_DS="&ds";
|
|
207
|
+
quit;
|
|
208
|
+
%if &syscc>0 %then %put syscc=&syscc sqlrc=&sqlrc;
|
|
209
|
+
%if &status=LOCKED %then %do;
|
|
210
|
+
data _null_;
|
|
211
|
+
putlog "&sysmacroname: unlocking &lib..&ds:";
|
|
212
|
+
run;
|
|
213
|
+
proc sql;
|
|
214
|
+
update &ctl_ds
|
|
215
|
+
set LOCK_STATUS_CD='UNLOCKED'
|
|
216
|
+
, LOCK_END_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
|
217
|
+
, LOCK_USER_NM="&user"
|
|
218
|
+
, LOCK_PID="&sysjobid"
|
|
219
|
+
, LOCK_REF="&ref"
|
|
220
|
+
where LOCK_LIB ="&lib" and LOCK_DS="&ds";
|
|
221
|
+
quit;
|
|
222
|
+
%end;
|
|
223
|
+
%else %if &status=UNLOCKED %then %do;
|
|
224
|
+
%put %str(WAR)NING: &lib..&ds is already unlocked!;
|
|
225
|
+
%end;
|
|
226
|
+
%else %do;
|
|
227
|
+
%put NOTE: Unrecognised STATUS_CD (&status) in &ctl_ds;
|
|
228
|
+
%let abortme=1;
|
|
229
|
+
%end;
|
|
223
230
|
%end;
|
|
224
231
|
%end;
|
|
225
232
|
%else %do;
|
package/macros/mp_md5.sas
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
@file
|
|
3
3
|
@brief Generates an md5 expression for hashing a set of variables
|
|
4
4
|
@details This is the same algorithm used to hash records in
|
|
5
|
-
[Data Controller for SAS](https://datacontroller.io)
|
|
6
|
-
to 5 users).
|
|
5
|
+
[Data Controller for SAS](https://datacontroller.io).
|
|
7
6
|
|
|
8
7
|
It is not designed to be efficient - it is designed to be effective,
|
|
9
8
|
given the range of edge cases (large floating points, special missing
|
|
@@ -29,8 +28,8 @@
|
|
|
29
28
|
@li Global option: `options dsoptions=nonote2err;`
|
|
30
29
|
@li Data step option: `data YOURLIB.YOURDATASET /nonote2err;`
|
|
31
30
|
|
|
32
|
-
@param cvars= Space seperated list of character variables
|
|
33
|
-
@param nvars= Space seperated list of numeric variables
|
|
31
|
+
@param [in] cvars= () Space seperated list of character variables
|
|
32
|
+
@param [in] nvars= () Space seperated list of numeric variables
|
|
34
33
|
|
|
35
34
|
<h4> Related Programs </h4>
|
|
36
35
|
@li mp_init.sas
|
package/macros/mp_perflog.sas
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
%mp_perflog(finished)
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
@param label Provide label to go into the control dataset
|
|
15
|
-
@param libds= Provide a dataset in which to store
|
|
16
|
-
|
|
14
|
+
@param [in] label Provide label to go into the control dataset
|
|
15
|
+
@param [in] libds= (work.mp_perflog) Provide a dataset in which to store
|
|
16
|
+
performance stats. Default name is <code>work.mp_perflog</code>;
|
|
17
17
|
|
|
18
18
|
@version 9.2
|
|
19
19
|
@author Allan Bowe
|
package/macros/mp_prevobs.sas
CHANGED
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
Credit is made to `data _null_` for authoring this very helpful paper:
|
|
35
35
|
https://www.lexjansen.com/pharmasug/2008/cc/CC08.pdf
|
|
36
36
|
|
|
37
|
-
@param action Either FETCH a current or previous record, or INITialise.
|
|
38
|
-
@param record The relative (to current) position of the previous
|
|
37
|
+
@param [in] action Either FETCH a current or previous record, or INITialise.
|
|
38
|
+
@param [in] record The relative (to current) position of the previous row
|
|
39
39
|
to return.
|
|
40
|
-
@param history= The number of records to retain in the hash table.
|
|
41
|
-
@param prefix=
|
|
42
|
-
and index.
|
|
40
|
+
@param [in] history= (5) The number of records to retain in the hash table.
|
|
41
|
+
@param [in] prefix= (mp_prevobs) The prefix to give to the variables used to
|
|
42
|
+
store the hash name and index.
|
|
43
43
|
|
|
44
44
|
@version 9.2
|
|
45
45
|
@author Allan Bowe
|
|
@@ -23,12 +23,13 @@
|
|
|
23
23
|
,childvar=c
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
-
@param base_ds= base table containing hierarchy (not modified)
|
|
27
|
-
@param outds= the output dataset to create with the generated hierarchy
|
|
28
|
-
@param matchval= the ultimate parent from which to filter
|
|
29
|
-
@param parentvar= name of the parent variable
|
|
30
|
-
@param childvar= name of the child variable (should be same type as
|
|
31
|
-
|
|
26
|
+
@param [in] base_ds= base table containing hierarchy (not modified)
|
|
27
|
+
@param [out] outds= the output dataset to create with the generated hierarchy
|
|
28
|
+
@param [in] matchval= the ultimate parent from which to filter
|
|
29
|
+
@param [in] parentvar= name of the parent variable
|
|
30
|
+
@param [in] childvar= () name of the child variable (should be same type as
|
|
31
|
+
parent)
|
|
32
|
+
@param [in] mdebug= set to 1 to prevent temp tables being dropped
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
@returns outds contains the following variables:
|
package/macros/mp_replace.sas
CHANGED
|
@@ -32,10 +32,11 @@
|
|
|
32
32
|
Note - if you are running a version of SAS that will allow the io package in
|
|
33
33
|
LUA, you can also use this macro: mp_gsubfile.sas
|
|
34
34
|
|
|
35
|
-
@param infile The QUOTED path to the file on which to perform the
|
|
36
|
-
|
|
37
|
-
@param
|
|
38
|
-
@param
|
|
35
|
+
@param [in] infile The QUOTED path to the file on which to perform the
|
|
36
|
+
substitution
|
|
37
|
+
@param [in] findvar= Macro variable NAME containing the string to search for
|
|
38
|
+
@param [in] replacevar= Macro variable NAME containing the replacement string
|
|
39
|
+
@param [out] outfile= (0) Optional QUOTED path to the adjusted output file (to
|
|
39
40
|
avoid overwriting the first file).
|
|
40
41
|
|
|
41
42
|
<h4> SAS Macros </h4>
|
package/macros/mp_runddl.sas
CHANGED
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
%mp_runddl(/some/rootlib, exc=LIBREF3) * same as above ;
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
@param path location of the DDL folder structure
|
|
35
|
-
@param inc= list of librefs to include
|
|
36
|
-
@param exc= list of librefs to exclude (takes precedence over inc=)
|
|
34
|
+
@param [in] path location of the DDL folder structure
|
|
35
|
+
@param [in] inc= list of librefs to include
|
|
36
|
+
@param [in] exc= list of librefs to exclude (takes precedence over inc=)
|
|
37
37
|
|
|
38
38
|
@version 9.3
|
|
39
39
|
@author Allan Bowe
|
package/macros/mp_searchcols.sas
CHANGED
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
|
|
10
10
|
%mp_searchcols(libs=sashelp work, cols=name sex age)
|
|
11
11
|
|
|
12
|
-
@param libs=(SASHELP)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
@param [in] libs= (SASHELP)
|
|
13
|
+
Space separated list of libraries to search for columns
|
|
14
|
+
@param [in] cols=
|
|
15
|
+
Space separated list of column names to search for (not case sensitive)
|
|
16
|
+
@param [out] outds= (mp_searchcols)
|
|
17
|
+
The table to create with the results. Will have one line per table match.
|
|
18
|
+
@param [in] match= (ANY) The match type. Valid values:
|
|
18
19
|
@li ANY - The table contains at least one of the columns
|
|
19
20
|
@li WILD - The table contains a column with a name that partially matches
|
|
20
21
|
|
package/macros/mp_stackdiffs.sas
CHANGED
|
@@ -197,6 +197,7 @@
|
|
|
197
197
|
@li mp_coretable.sas
|
|
198
198
|
@li mp_stackdiffs.test.sas
|
|
199
199
|
@li mp_storediffs.sas
|
|
200
|
+
@li mp_stripdiffs.sas
|
|
200
201
|
|
|
201
202
|
@todo The current approach assumes that a variable called KEY_HASH is not on
|
|
202
203
|
the base table. This part will need to be refactored (eg using
|
package/macros/mp_storediffs.sas
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
data recovery, and change re-application. This macro is one of many
|
|
7
7
|
data management utilities used in [Data Controller for SAS](
|
|
8
8
|
https:datacontroller.io) - a comprehensive data ingestion solution, which
|
|
9
|
-
works on any SAS platform (Viya, SAS 9, Foundation)
|
|
10
|
-
users.
|
|
9
|
+
works on any SAS platform (Viya, SAS 9, Foundation).
|
|
11
10
|
|
|
12
11
|
NOTE - this macro does not validate the inputs. It is assumed that the
|
|
13
12
|
datasets containing the new / changed / deleted rows are CORRECT, contain
|
|
@@ -65,6 +64,7 @@
|
|
|
65
64
|
<h4> Related Macros </h4>
|
|
66
65
|
@li mp_stackdiffs.sas
|
|
67
66
|
@li mp_storediffs.test.sas
|
|
67
|
+
@li mp_stripdiffs.sas
|
|
68
68
|
|
|
69
69
|
@version 9.2
|
|
70
70
|
@author Allan Bowe
|
|
@@ -147,9 +147,9 @@ run;
|
|
|
147
147
|
|
|
148
148
|
%if %index(&libds,-)>0 and %scan(&libds,2,-)=FC %then %do;
|
|
149
149
|
/* this is a format catalog - cannot query cols directly */
|
|
150
|
-
%let vlist="FMTNAME","START","END","LABEL","MIN","MAX"
|
|
151
|
-
,"FUZZ","PREFIX","MULT","FILL","NOEDIT","
|
|
152
|
-
,"DECSEP","DIG3SEP","DATATYPE","LANGUAGE";
|
|
150
|
+
%let vlist="TYPE","FMTNAME","FMTROW","START","END","LABEL","MIN","MAX"
|
|
151
|
+
,"DEFAULT","LENGTH","FUZZ","PREFIX","MULT","FILL","NOEDIT","SEXCL"
|
|
152
|
+
,"EEXCL","HLO","DECSEP","DIG3SEP","DATATYPE","LANGUAGE";
|
|
153
153
|
%end;
|
|
154
154
|
%else %let vlist=%mf_getvarlist(&libds,dlm=%str(,),quote=DOUBLE);
|
|
155
155
|
|
|
@@ -165,7 +165,7 @@ data &ds4;
|
|
|
165
165
|
if upcase(&inds_auto)="&ds2" then tgtvar_type='N';
|
|
166
166
|
else if upcase(&inds_auto)="&ds3" then tgtvar_type='C';
|
|
167
167
|
else do;
|
|
168
|
-
putlog
|
|
168
|
+
putlog 'ERR' +(-1) "OR: unidentified vartype input!" &inds_auto;
|
|
169
169
|
call symputx('syscc',98);
|
|
170
170
|
end;
|
|
171
171
|
|
|
@@ -174,7 +174,7 @@ data &ds4;
|
|
|
174
174
|
else if &inds_keep="&modds" then move_type='M';
|
|
175
175
|
else if &inds_keep="&origds" then move_type='O';
|
|
176
176
|
else do;
|
|
177
|
-
putlog
|
|
177
|
+
putlog 'ERR' +(-1) "OR: unidentified movetype input!" &inds_keep;
|
|
178
178
|
call symputx('syscc',99);
|
|
179
179
|
end;
|
|
180
180
|
tgtvar_nm=upcase(tgtvar_nm);
|
|
@@ -184,7 +184,7 @@ data &ds4;
|
|
|
184
184
|
run;
|
|
185
185
|
|
|
186
186
|
%if "&loadref"="0" %then %let loadref=%sysfunc(uuidgen());
|
|
187
|
-
%if &processed_dttm=0 %then %let processed_dttm=%sysfunc(datetime());
|
|
187
|
+
%if &processed_dttm=0 %then %let processed_dttm=%sysfunc(datetime(),8.6);
|
|
188
188
|
%let libds=%upcase(&libds);
|
|
189
189
|
|
|
190
190
|
/* join orig vals for modified & deleted */
|
|
@@ -21,9 +21,10 @@
|
|
|
21
21
|
%mp_stprequests(status_cd=INIT, libds=YOURLIB.DATASET )
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
@param status_cd= Use INIT for INIT and TERM for TERM events
|
|
25
|
-
@param libds= Location of base table
|
|
26
|
-
of table locks, we HIGHLY recommend
|
|
24
|
+
@param [in] status_cd= Use INIT for INIT and TERM for TERM events
|
|
25
|
+
@param [in] libds= (somelib.stp_requests) Location of base table
|
|
26
|
+
(library.dataset). To minimise risk of table locks, we HIGHLY recommend
|
|
27
|
+
using a database (NOT a SAS dataset).
|
|
27
28
|
THE LIBRARY SHOULD BE ASSIGNED ALREADY - eg in autoexec or earlier in the
|
|
28
29
|
init program proper.
|
|
29
30
|
|