Loading...
Searching...
No Matches
mpe_targetloader.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Generic loader for tables configured in &mpelib..mpe_tables
4 @details General wrapper for loading tables using ALL load types.
5
6 Called by admin/postdata. The dclib should already be assigned.
7
8 @param [in] dclib= (NOTPROVIDED) The data controller control library
9 @param [in] libds= the library.dataset to load
10 @param [in] now= (%sysfunc(datetime())) Static processed timestamp
11
12 <h4> SAS Macros </h4>
13 @li bitemporal_dataloader.sas
14 @li mf_existvar.sas
15 @li mf_getengine.sas
16 @li mf_getuniquename.sas
17 @li mp_abort.sas
18 @li mp_loadformat.sas
19 @li mp_lockanytable.sas
20
21 @version 9.2
22 @author 4GL Apps Ltd
23 @copyright 4GL Apps Ltd. This code may only be used within Data Controller
24 and may not be re-distributed or re-sold without the express permission of
25 4GL Apps Ltd.
26
27**/
28
29%macro mpe_targetloader(libds= /* library.dataset to LOAD (target) */
30 ,now= %sysfunc(datetime()) /* static processed timestamp */
31 ,etlsource= /* process from whence the data came */
32 ,STAGING_DS= STAGING_DS /* name of staging (work) dataset which should
33 be appended into the target. */
34 ,LOADTARGET=NO /* set to yes to actually load the target */
35 ,CLOSE_VARS= /* provide close vars to override defaults */
36 ,dclib=NOTPROVIDED
37 ,mdebug=0
38 ,dc_dttmtfmt=%sysfunc(datetime())
39 );
40%local lib ds nobs;
41
42/**
43 * if a format catalog (suffix "-FC") we assume the catalog has already been
44 * created by the calling program with a libds of work.fmtextract
45*/
46%let orig_lib=%upcase(%scan(&libds,1,.));
47%let orig_ds=%upcase(%scan(&libds,2,.));
48%let orig_libds=&libds;
49%if %scan(&libds,2,-)=FC %then %do;
50 %let lib=WORK;
51 %let ds=FMTEXTRACT;
52 %let libds=&lib..&ds;
53%end;
54%else %do;
55 %let lib=&orig_lib;
56 %let ds=&orig_ds;
57%end;
58
59%mp_abort(iftrue= (&dclib=NOTPROVIDED)
60 ,mac=&sysmacroname
61 ,msg=%str(dclib=NOTPROVIDED)
62)
63
64/* get table attributes */
65%let nobs=0;
66data work.sumo_config;
67 set &mpelib..mpe_tables;
68 where &dc_dttmtfmt. lt tx_to
69 and libref="&orig_lib"
70 and dsn="&orig_ds";
71 call symputx('LOADTYPE',loadtype,'l');
72 call symputx('BUSKEY',buskey,'l');
73 call symputx('VAR_TXFROM',var_txfrom,'l');
74 call symputx('VAR_TXTO',var_txto,'l');
75 call symputx('VAR_BUSFROM',var_busfrom,'l');
76 call symputx('VAR_BUSTO',var_busto,'l');
77 call symputx('VAR_PROCESSED',VAR_PROCESSED,'l');
78 call symputx('RK_UNDERLYING',RK_UNDERLYING,'l');
79 %if %length(&CLOSE_VARS)=0 %then %do;
80 call symputx('CLOSE_VARS',CLOSE_VARS,'l');
81 %end;
82 call symputx('nobs',_n_,'l');
83 if missing(AUDIT_LIBDS) then AUDIT_LIBDS="&dclib..MPE_AUDIT";
84 call symputx('AUDIT_LIBDS',AUDIT_LIBDS,'l');
85 put (_all_)(=);
86run;
87
88/* check if table is actually configured to load */
89%if &nobs ne 1 %then %do;
90 proc sql;
91 insert into &mpelib..mpe_loads
92 set USER_NM="%mf_getuser()"
93 ,STATUS='FAILED (BAD DS)'
94 ,CSV_DIR=symget('ETLSOURCE')
95 ,PROCESSED_DTTM=&now;
96%end;
97%mp_abort(iftrue= (&nobs=0)
98 ,mac=&sysmacroname
99 ,msg=%str(Table not registered in &mpelib..mpe_tables)
100)
101%mp_abort(iftrue= (&nobs>1)
102 ,mac=&sysmacroname
103 ,msg=%str(Something is very wrong with the PK in &mpelib..mpe_tables)
104)
105
106
107%if &LOADTYPE=TXTEMPORAL %then %do;
108
109 %bitemporal_dataloader(bus_from=,bus_to= /* explicitly empty*/
110 ,tech_from=&VAR_TXFROM
111 ,tech_to = &VAR_TXTO
112 ,base_lib=&lib
113 ,base_dsn=&ds
114 ,append_lib=WORK
115 ,append_dsn=&STAGING_DS
116 ,high_date='31DEC9999:23:59:59'dt
117 ,PK= &buskey
118 ,ETLSOURCE=&ETLSOURCE
119 ,LOADTYPE=&loadtype
120 ,RK_UNDERLYING=&RK_UNDERLYING
121 ,LOADTARGET=&LOADTARGET
122 ,RK_UPDATE_MAXKEYTABLE=&LOADTARGET
123 ,CLOSE_VARS=&CLOSE_VARS
124 ,processed=&VAR_PROCESSED
125 ,dclib=&dclib
126 ,outds_audit=&AUDIT_LIBDS
127 )
128%end;
129%else %if &loadtype=REPLACE %then %do;
130 %if &LOADTARGET=YES %then %do;
131 %mp_lockanytable(LOCK,lib=&lib,ds=&ds,ref=%str(&etlsource),
132 ctl_ds=&dclib..mpe_lockanytable
133 )
134 data WORK.&STAGING_DS;
135 set WORK.&STAGING_DS;
136 %if %mf_existvar(&libds,&VAR_PROCESSED) %then %do;
137 &VAR_PROCESSED = &now;
138 %end;
139 drop _____DELETE__THIS__RECORD_____;
140 run;
141 %local engine_type;
142 %let engine_type=%mf_getengine(&lib);
143 %if &engine_type=CAS %then %do;
144 /* Fixed char variables cannot be appended to CAS varchar columns, so
145 cast them (per the target table structure) in a CASUSER copy of the
146 staging table, then append via data step. Approach mirrors the CAS
147 append in bitemporal_dataloader.sas */
148 proc contents noprint data=&libds
149 out=work.rpl_base_cols(keep=name type);
150 run;
151 proc contents noprint data=WORK.&STAGING_DS
152 out=work.rpl_stag_cols(keep=name type);
153 run;
154 proc sql noprint;
155 create table work.rpl_vchars as
156 select a.name
157 from work.rpl_base_cols a
158 inner join work.rpl_stag_cols b
159 on upcase(a.name)=upcase(b.name)
160 where a.type=6; /* varchar in target */
161 quit;
162 /* get varchar variables ready for casting */
163 %local vcfmt vcrename vcassign vcdrop tmpds;
164 %let vcfmt=;
165 %let vcrename=;
166 %let vcassign=;
167 %let vcdrop=;
168 data _null_;
169 set work.rpl_vchars end=last;
170 length vcrename vcassign vcdrop vcfmt $32767 rancol $32;
171 retain vcrename vcassign vcdrop vcfmt;
172 if _n_=1 then vcrename='(rename=(';
173 rancol=resolve('%mf_getuniquename()');
174 vcfmt=trim(vcfmt)!!'length '!!cats(name)!!' varchar(*);';
175 vcrename=trim(vcrename)!!' '!!cats(name,'=',rancol);
176 vcassign=cats(vcassign,name,'=',rancol,';');
177 vcdrop=cats(vcdrop,'drop '!!rancol,';');
178 if last then do;
179 vcrename=cats(vcrename,'))');
180 call symputx('vcfmt',vcfmt);
181 call symputx('vcrename',vcrename);
182 call symputx('vcassign',vcassign);
183 call symputx('vcdrop',vcdrop);
184 end;
185 run;
186 /* prepare a temp cas table with varchars casted */
187 %let tmpds=%mf_getuniquename();
188 data casuser.&tmpds;
189 &vcfmt
190 set WORK.&STAGING_DS &vcrename;
191 &vcassign
192 &vcdrop
193 run;
194 /* exit on err condition before the destructive truncate below */
195 %if &syscc>0 %then %do;
196 %mp_lockanytable(UNLOCK,lib=&lib,ds=&ds,ref=&ETLSOURCE (aborted),
197 ctl_ds=&dclib..mpe_lockanytable
198 )
199 /* ensure cleanup */
200 proc sql;drop table CASUSER.&tmpds;quit;
201 %end;
202 %mp_abort(iftrue= (&syscc>0)
203 ,mac=&sysmacroname
204 ,msg=%str(syscc=&syscc - aborting before REPLACE truncate of &libds.)
205 )
206 /* CAS tables do not support SQL deletes, so truncate with deleteRows.
207 This is deliberately the last step before the append, to minimise
208 the time in which the target table is empty. */
209 proc cas;
210 table.deleteRows / table={caslib="&lib",name="&ds",where="1=1"};
211 quit;
212 /* load the target with varchars applied */
213 data &libds (append=yes) / sessref=dcsession;
214 set casuser.&tmpds;
215 run;
216 /* drop temp table */
217 proc sql;
218 drop table CASUSER.&tmpds;
219 quit;
220 %end;
221 %else %do;
222 /* exit on err condition before the destructive delete below */
223 %if &syscc>0 %then %do;
224 %mp_lockanytable(UNLOCK,lib=&lib,ds=&ds,ref=&ETLSOURCE (aborted),
225 ctl_ds=&dclib..mpe_lockanytable
226 )
227 %end;
228 %mp_abort(iftrue= (&syscc>0)
229 ,mac=&sysmacroname
230 ,msg=%str(syscc=&syscc - aborting before REPLACE delete of &libds.)
231 )
232 proc sql;
233 delete * from &libds;
234 quit;
235 proc append base=&libds data=WORK.&STAGING_DS force nowarn;run;
236 %end;
237
238 %mp_lockanytable(UNLOCK,lib=&lib,ds=&ds,ctl_ds=&dclib..mpe_lockanytable)
239 %end;
240 %else %do;
241 /* is full replace so treat all staged records as new in diff screen */
242 data work.outds_mod work.outds_add ;
243 set work.&staging_ds;
244 output work.outds_add;
245 run;
246 /* previous table will be considered fully deleted */
247 data work.outds_del;
248 set &lib..&ds;
249 run;
250 %end;
251%end;
252%else %if &loadtype=UPDATE %then %do;
253 %bitemporal_dataloader(bus_from=,bus_to=
254 ,tech_from= ,tech_to = /* explicitly empty*/
255 ,base_lib=&lib
256 ,base_dsn=&ds
257 ,append_lib=WORK
258 ,append_dsn=&STAGING_DS
259 ,high_date='31DEC9999:23:59:59'dt
260 ,PK= &buskey
261 ,ETLSOURCE=%superq(etlsource)
262 ,LOADTYPE=UPDATE
263 ,RK_UNDERLYING=&RK_UNDERLYING
264 ,LOADTARGET=&LOADTARGET
265 ,RK_UPDATE_MAXKEYTABLE=&LOADTARGET
266 ,processed=&VAR_PROCESSED
267 ,dclib=&dclib
268 ,outds_audit=&AUDIT_LIBDS
269 )
270%end;
271%else %if &loadtype=FORMAT_CAT %then %do;
272 /**
273 * run mp_formatload
274 * inputs:
275 * - LOADTARGET
276 * - CATALOG
277 * - STAGEDATA
278 * - LOADAUDIT
279 * outputs:
280 * work.outds_add
281 * work.outds_del
282 * work.outds_mod
283 */
284 %mp_loadformat(&orig_libds
285 ,&staging_ds
286 ,loadtarget=&LOADTARGET
287 ,auditlibds=&AUDIT_LIBDS
288 ,locklibds=&dclib..mpe_lockanytable
289 ,delete_col=_____DELETE__THIS__RECORD_____
290 ,outds_add=outds_add
291 ,outds_del=outds_del
292 ,outds_mod=outds_mod
293 ,mdebug=&mdebug
294 )
295%end;
296%else %if &loadtype=BITEMPORAL %then %do;
297 %bitemporal_dataloader(bus_from=&VAR_BUSFROM,bus_to=&VAR_BUSTO
298 ,tech_from=&VAR_TXFROM
299 ,tech_to = &VAR_TXTO
300 ,base_lib=&lib
301 ,base_dsn=&ds
302 ,append_lib=WORK
303 ,append_dsn=&STAGING_DS
304 ,high_date='31DEC9999:23:59:59'dt
305 ,PK= &buskey
306 ,ETLSOURCE=%superq(etlsource)
307 ,LOADTYPE=BITEMPORAL
308 ,RK_UNDERLYING=&RK_UNDERLYING
309 ,LOADTARGET=&LOADTARGET
310 ,RK_UPDATE_MAXKEYTABLE=&LOADTARGET
311 ,CLOSE_VARS=&CLOSE_VARS
312 ,processed=&VAR_PROCESSED
313 ,dclib=&dclib
314 ,outds_audit=&AUDIT_LIBDS
315 )
316%end;
317%else %do;
318 %put %str(WARN)ING: LOADTYPE &LOADTYPE not supported;
319 %let syscc=4;
320 %mp_abort(msg=LOADTYPE &LOADTYPE not supported,mac=mpe_targetloader.sas)
321%end;
322
323%mp_abort(iftrue= (&syscc ne 0)
324 ,mac=&_program
325 ,msg=%str(syscc=&syscc exiting MPE_TARGETLOADER macro)
326)
327
328%mend mpe_targetloader;