File Coverage

blib/lib/PeopleSoft/EPM.pm
Criterion Covered Total %
statement 15 48 31.2
branch 0 4 0.0
condition n/a
subroutine 5 9 55.5
pod n/a
total 20 61 32.7


line stmt bran cond sub pod time code
1             # Copyright (c) 2003 William Goedicke. All rights reserved. This
2             # program is free software; you can redistribute it and/or modify it
3             # under the same terms as Perl itself.
4              
5             =head1 NAME
6              
7             PeopleSoft::EPM - Functions for EPM
8              
9             =head1 SYNOPSIS
10              
11             use PeopleSoft::EPM;
12             my $result = remove_grp($grpid,$dbh);
13             my $result = create_grp(\@grp,,$grpid,$parallelflag $dbh)
14             my $result = release_recsuite($rs_id, $js_id, $dbh);
15             my $return = ren_repository($old_name, $new_name, $dbh);
16             my ( $maps, $srcs, $tgts, $lkps ) = get_mapping_structs( $app_aref, $dbh );
17             recurse( $mapping, $load_seq, $MS, $SS, $TS );
18             my $mapname = get_mapname_with_target( $target_name, $dbh );
19             my $mapname = get_mapname_with_source( $source_name, $dbh );
20              
21             =cut
22              
23             package PeopleSoft::EPM;
24 1     1   1570 use DBI;
  1         3  
  1         42  
25 1     1   6 use strict;
  1         2  
  1         35  
26 1     1   5 use Data::Dumper;
  1         2  
  1         42  
27 1     1   6 use Exporter;
  1         2  
  1         34  
28 1     1   6 use vars qw(@ISA @EXPORT);
  1         2  
  1         14240  
29             @ISA = qw(Exporter);
30              
31             @EXPORT = qw(remove_grp
32             create_grp
33             release_recsuite
34             get_mapping_structs
35             recurse
36             ren_repository
37             dl_run_seq
38             get_maps_aref
39             );
40              
41             =head1 DESCRIPTION
42              
43             This module provides functionality associated with running
44             the data loader utility to move data from ODS staging into
45             the enterprise warehouse.
46              
47             This module also provides a set of functions to query and manipulate
48             the informatica mappings.
49              
50              
51             =cut
52              
53             # --------------------------------- remove_grp()
54              
55             =over 3
56              
57             =item remove_grp($grpid, $dbh)
58              
59             The remove_grp() deletes the specified data loader map
60             group from the database associated with $dbh.
61              
62             =back
63              
64             =cut
65              
66             sub remove_grp{
67 0     0     my ($grpid,$dbh) = @_;
68 0           my @sql_cmd;
69 0           $sql_cmd[0] = "delete from ps_pf_dl_grp_defn where pf_dl_grp_id = '$grpid'";
70 0           $sql_cmd[1] = "delete from ps_pf_dl_grp_step where pf_dl_grp_id = '$grpid'";
71 0           foreach (@sql_cmd){
72 0           $dbh->do($_);
73 0           $dbh->commit;
74             }
75             }
76             # --------------------------------- create_grp()
77              
78             =over 3
79              
80             =item create_grp(\@grp,,$grpid,$parallelflag $dbh)
81              
82             create_grp creates a data loader map group including all the
83             maps in $maps_aref with description of $mapdesc and a group
84             id of $grpid. The function will mark the group with $parallelflg,
85             valid values are 'Y' and 'N'.
86              
87             =back
88              
89             =cut
90              
91             sub create_grp{
92 0     0     my ($maps_aref,$mapdesc,$grpid,$parallelflag,$dbh) = @_;
93 0           my $counter = 1;
94            
95 0           my $sql_cmd = "insert into ps_pf_dl_grp_defn
96             (PF_DL_GRP_ID, PF_DL_GRP_STATUS, DESCR,
97             PF_DL_RUN_PARALLEL, PF_SYS_MAINT_FLG, DESCRLONG)
98             values ('$grpid',' ','$mapdesc','$parallelflag',' ',
99             '$mapdesc')";
100 0           $dbh->do($sql_cmd);
101            
102 0           foreach my $mapname ( @{$maps_aref} ) {
  0            
103 0           my $sql_cmd =
104             "INSERT INTO PS_PF_DL_GRP_STEP
105             (PF_DL_GRP_ID,PF_DL_ROW_NUM,PF_ODS_SEQ,PF_DL_GRP_ENT_TYP,
106             DS_MAPNAME,PF_DL_GRP_ENT_STAT,PF_DL_GRP_EXEC,DESCR,
107             PROCESS_INSTANCE,TABLE_APPEND,DATAMAP_COL_SEQ,
108             PF_DL_COL_DESCR,PF_SQL_ALIAS,FIELDNAME,PF_DL_LT_JOIN_OPER,
109             METAVALUE,PF_SYS_MAINT_FLG,WHERECHUNK)
110             VALUES('$grpid',$counter,$counter,'M','$mapname',' ',' ',' ',
111             0,' ',0,' ',' ',' ','=',' ',' ',' ')";
112 0           $counter++;
113 0 0         if ( defined $dbh->do($sql_cmd) ) { $dbh->commit; }
  0            
114             }
115             }
116              
117             #------------------------------------ release_recsuite
118              
119             =over 3
120              
121             =item release_recsuite( $rs_id, $js_id, $dbh )
122              
123             Specifying a record suite id (e.g. 001) and a jobstream id
124             (e.g. PS_DL_RUN) will release the recordsuite in the database
125             with handle $dbh.
126              
127             =back
128              
129             =cut
130              
131             sub release_recsuite {
132 0     0     my ( $rs_id, $js_id, $dbh ) = @_;
133              
134 0           my @sql_cmd =
135             ( "update ps_pf_recsuite_tbl set in_use_sw = 'N'
136             where recsuite_id = '$rs_id'",
137              
138             "Update PS_PF_TEMP_REC_TBL Set PF_MERGE_FLG = 'N',
139             PF_RERUN_OVERRIDE = 'N',
140             PF_SELECT_WHERE = ' ',
141             PF_MERGE_LOCK = 'N'
142             where recsuite_id = '$rs_id'",
143              
144             "Update PS_PF_TEMP_RL_TBL
145             Set PF_RERUN_OVERRIDE = 'N'
146             where recsuite_id = '$rs_id'",
147              
148             "UPDATE PS_PF_JOBSTRM_TBL
149             SET JOBSTREAM_STATUS='N',
150             job_id=' ',
151             business_unit=' ',
152             pf_scenario_id=' ',
153             run_cntl_id=' ',
154             IN_USE_SW='N',
155             PROCESS_INSTANCE=0
156             WHERE JOBSTREAM_ID='$js_id'
157             AND recsuite_id = '$rs_id'",
158              
159             "SELECT RECSUITE_ID, TO_CHAR(DTTM_STAMP,
160             'YYYY-MM-DD-HH24.MI.SS.\"000000\"'), IN_USE_SW,
161             JOB_ID, PROCESS_INSTANCE, RUN_CNTL_ID,
162             PF_SPAWN_ID, PF_CHUNK_LOCK FROM PS_PF_RECSUITE_TBL
163             WHERE RECSUITE_ID='$rs_id' FOR UPDATE OF IN_USE_SW" );
164              
165 0           foreach my $cmd ( @sql_cmd ) {
166 0 0         if ( ! defined $dbh->do($cmd) ) {
167 0           die "Uh oh! Failed to execute $cmd\n";
168             }
169             }
170 0           $dbh->commit;
171             }
172             #----------------------------------------------------
173              
174             =over 3
175              
176             =item get_maps_aref( $fldr_aref, $dbh )
177              
178             This function returns a reference to an array that contains
179             the names of all the data loader maps associated with any of
180             the "folders" contained in the array of the first parameter.
181              
182             =back
183              
184             =cut
185              
186             sub get_maps_aref {
187 0     0     my ( $apps, $dbh ) = @_;
188 0           my ( $maps, @results );
189              
190 0           my $sql_cmd = "select ds_mapname from ps_pf_dl_map_defn where folder_name = 'HR'";
191              
192 0           my $sth = $dbh->prepare($sql_cmd);
193 0           $sth->execute;
194 0           while( @results = $sth->fetchrow_array ) {
195 0           push( @{$maps}, $results[0]);
  0            
196             }
197 0           $sth->finish;
198              
199 0           return( $maps );
200             }
201             #------------------------------------------------------------
202             sub dl_run_seq {
203             my ( $fldr_aref, $dbh ) = @_;
204             my ( %mappings, @results, @r2, $mapnames );
205              
206             my $sql_cmd = "select ds_mapname from ps_pf_dl_map_defn ";
207             if ( @{$fldr_aref} == 1 ) {
208             $sql_cmd .= "where folder_name = '$$fldr_aref[0]'";
209             }
210             elsif ( @{$fldr_aref} > 1 ) {
211             $sql_cmd .= "where folder_name = '", join "' or folder_name = '", @{$fldr_aref}, "'";
212             }
213             else { die "You have to supply at least one folder to dl_run_seq"; }
214              
215             my $sth = $dbh->prepare($sql_cmd);
216             $sth->execute;
217             while( @results = $sth->fetchrow_array ) { $mappings{$results[0]} = '';
218             $sql_cmd = "select distinct ds_source_rec, edittable from PS_PF_DL_MAPDET_VW
219             where ds_mapname = '$results[0]' and
220             ds_source_rec not like ' ' and
221             edittable not like ' '";
222             my $sth2 = $dbh->prepare($sql_cmd);
223             $sth2->execute;
224             while( @r2 = $sth2->fetchrow_array ) {
225             @results = @{populate_mapnames( $r2[0], 'SRC', \@results, \%mappings, $dbh)};
226             @results = @{populate_mapnames( $r2[1], 'LKP', \@results, \%mappings, $dbh)};
227             }
228             $sth2->finish;
229              
230             $sql_cmd = "select distinct lookup_tbl from ps_pf_dl_edt_defn
231             where ds_mapname = '$results[0]'
232             and lookup_tbl not like ' '";
233             $sth2 = $dbh->prepare($sql_cmd);
234             $sth2->execute;
235             while( @r2 = $sth2->fetchrow_array ) {
236             @results = @{populate_mapnames( $r2[0], 'EDT', \@results, \%mappings, $dbh)};
237             }
238             $sth2->finish;
239             $sql_cmd = "select distinct lookup_tbl from ps_pf_dl_trn_defn
240             where ds_mapname = '$results[0]'
241             and lookup_tbl not like ' '";
242             $sth2 = $dbh->prepare($sql_cmd);
243             $sth2->execute;
244             while( @r2 = $sth2->fetchrow_array ) {
245             @results = @{populate_mapnames( $r2[0], 'TRN', \@results, \%mappings, $dbh)};
246             }
247             $sth2->finish;
248             }
249             $sth->finish;
250              
251             my ( %mn2 );
252              
253             foreach my $k ( sort keys %mappings ) {
254             foreach my $type qw( SRC LKP TRN ) {
255             foreach my $k2 ( keys %{$mappings{$k}{$type}} ) {
256             if ( $k eq 'PERSONAL_D00' and $k2 eq 'JOB_F00' ) {next;}
257             if ( defined $mappings{$k2} and $k2 ne $k ) { $mn2{$k}{$k2} = ''; }
258             }
259             }
260             }
261              
262             return(\%mappings);
263              
264             my ( @ordered_dl_maps, $k, %done );
265              
266             foreach my $map ( sort keys %mappings ) {
267             # print "M: $map\n";
268             if ( defined $done{$map} ) { next; }
269             push @ordered_dl_maps, dl_recurse( $map, \%mn2, \%done, \@ordered_dl_maps );
270             if ( defined $done{$map} ) { next; }
271             # print "PUSHED1: $ordered_dl_maps[-1]\n";
272             push @ordered_dl_maps, $map;
273             $done{$map} = 1;
274             # print "PUSHED2: $ordered_dl_maps[-1]\n";
275             }
276              
277             my @uniq;
278             my %seen = ();
279             foreach my $item ( @ordered_dl_maps ){
280             push(@uniq, $item) unless $seen{$item}++;
281             }
282             return(\@uniq);
283             }
284             #------------------------------------------------------------
285             sub dl_recurse {
286             my ( $seed, $mn2, $done, $ordered_dl_maps ) = @_;
287              
288             foreach my $k ( keys %{$mn2->{$seed}} ) {
289             if ( ! defined $done->{$k} ) { dl_recurse( $k, $mn2, $done, $ordered_dl_maps ); }
290             }
291             push @{$ordered_dl_maps}, $seed;
292             $done->{$seed} = 1;
293             return $seed;
294             }
295             #------------------------------------------------------------
296             sub populate_mapnames {
297             my ( $obj_name, $obj_type, $results, $mapnames, $dbh ) = @_;
298             my ( $tbl_aref, $tbl );
299              
300             print "1:$obj_name, 2:$obj_type, 3:$results, 4:$mapnames, 5:$dbh\n";
301              
302             if ( PeopleSoft::Tables::is_view("PS_$obj_name", $dbh) ) {
303             print "is view\n";
304             $mapnames->{$results->[0]}{VIEWS}{$obj_name} = '';
305             $tbl_aref = where_from("PS_$obj_name", $dbh);
306             if ( defined @{$tbl_aref} ) {
307             foreach $tbl ( @{$tbl_aref} ) {
308             $tbl =~ s/^PS_//;
309             $mapnames->{$results->[0]}{$obj_type}{$tbl} = '';
310             }
311             }
312             } else {
313             print "0:$mapnames, 1:$results->[0], 2:$obj_type, 3:$obj_name\n";
314             # $mapnames->{$results->[0]}{$obj_type}{$obj_name} = 0;
315             }
316             }
317             # --------------------------------- ren_repository()
318              
319             =over 3
320              
321             =item ren_repository($old_name, $new_name, $dbh)
322              
323             The ren_repository() function changes the name of an Informatica
324             repository. It returns 1 on success and 0 on failure.
325              
326             =back
327              
328             =cut
329              
330             sub ren_repository {
331             my ( $old_name, $new_name, $dbh ) = @_;
332             my ( $rec_count );
333              
334             my $sql_cmd = "select count(*) from OPB_REPOSIT";
335             $sql_cmd .= " where REPOSIT_NAME = $old_name";
336             my $sth = $dbh->prepare($sql_cmd);
337             $sth->execute;
338             while ( ($rec_count) = $sth->fetchrow_array ) {
339             if ( $rec_count != 1 ) {
340             $sth->finish;
341             return 0;
342             }
343             }
344             $sth->finish;
345              
346             $sql_cmd = "select count(*) from OPB_REPOSIT_INFO";
347             $sql_cmd .= " where REPOSITORY_NAME = $old_name";
348             my $sth = $dbh->prepare($sql_cmd);
349             $sth->execute;
350             while ( ($rec_count) = $sth->fetchrow_array ) {
351             if ( $rec_count != 1 ) {
352             $sth->finish;
353             return 0;
354             }
355             }
356             $sth->finish;
357              
358             $sql_cmd = "update OPB_REPOSIT";
359             $sql_cmd .= " set REPOSIT_NAME = '$new_name'";
360             $sql_cmd .= " where REPOSIT_NAME = '$old_name'";
361             if ( ! ($sth = $dbh->prepare($sql_cmd)) ) { return 0; }
362             $sth->execute;
363              
364             $sql_cmd = "update OPB_REPOSIT_INFO";
365             $sql_cmd .= " set REPOSITORY_NAME = '$new_name'";
366             $sql_cmd .= " where REPOSITORY_NAME = '$old_name'";
367             if ( ! ($sth = $dbh->prepare($sql_cmd)) ) { return 0; }
368             $sth->execute;
369             $dbh->commit;
370             return 1;
371             }
372              
373             # ----------------------------------------------------------------------
374              
375             =over 3
376              
377             =item $mapname = get_mapname_with_target( $target_name, $dbh );
378              
379             This function returns a reference to an array of map names that populate the
380             table with the given name.
381              
382             =back
383              
384             =cut
385              
386             sub get_mapname_with_target {
387             my ( $target_name, $dbh ) = @_;
388             my ( @results, @maps );
389             my $sql_cmd =
390             "select opb_mapping.mapping_name
391             from opb_mapping, opb_widget_inst, opb_targ
392             where opb_mapping.mapping_id = opb_widget_inst.mapping_id
393             and opb_targ.target_id = opb_widget_inst.widget_id
394             and opb_targ.target_name = '$target_name'
395             and opb_widget_inst.widget_type = 2";
396              
397             my $sth = $dbh->prepare($sql_cmd);
398             $sth->execute;
399             while ( ( @results ) = $sth->fetchrow_array ) {
400             push @maps, $results[0];
401             }
402             $sth->finish;
403              
404             return \@maps;
405             }
406              
407             # ----------------------------------------------------------------------
408              
409             =over 3
410              
411             =item $mapname = get_mapname_with_source( $source_name, $dbh );
412              
413             This function returns a reference to an array of map names that are fed by the
414             table with the given name.
415              
416             =back
417              
418             =cut
419              
420             sub get_mapname_with_source {
421             my ( $source_name, $dbh ) = @_;
422             my ( @results, @maps );
423             my $sql_cmd =
424             "select opb_mapping.mapping_name
425             from opb_mapping, opb_widget_inst, opb_src
426             where opb_mapping.mapping_id = opb_widget_inst.mapping_id
427             and opb_widget_inst.widget_type = 1
428             and opb_src.src_id = opb_widget_inst.widget_id
429             and opb_src.source_name = '$source_name'";
430              
431              
432             my $sth = $dbh->prepare($sql_cmd);
433             $sth->execute;
434             while ( ( @results ) = $sth->fetchrow_array ) {
435             push @maps, $results[0];
436             }
437             $sth->finish;
438              
439             return \@maps;
440             }
441              
442             # ----------------------------------------------------------------------
443              
444             =over 3
445              
446             =item ( $maps, $srcs, $tgts, $lkps ) = get_mapping_structs( $app_aref, $dbh );
447              
448             This function returns references to four seperate hashes that contain critical
449             dependency information regarding informatica maps. The first (i.e. $maps)
450             contains sections for: source tables, target tables, and lookups. The other
451             three are simply inversions to expedite searchs.
452              
453             The function takes an array reference containing "applications" whose maps you
454             want to get information on and a database handle that point to the informatica
455             you are analyzing.
456              
457             =back
458              
459             =cut
460              
461             sub get_mapping_structs {
462             my ( $app_aref, $dbh, $map_name ) = @_;
463             my ( @results, @r2, $tbl_name, %mappings, %sources, %targets, %lookups );
464             my ( $mapping, $name_clause );
465             my @apps = @{$app_aref};
466              
467             if ( defined $map_name ) {
468             $name_clause = "opb_mapping.mapping_name = '$map_name'";
469             }
470             else {
471             $name_clause = "opb_mapping.mapping_name like '";
472             $name_clause .= join "\%' or opb_mapping.mapping_name like '", @apps;
473             $name_clause .= "\%'";
474             }
475              
476             # -------------- First we push the lookups onto the mappings struct
477              
478             my $sql_cmd =
479             "select distinct opb_mapping.mapping_name, opb_widget_attr.attr_value
480             from opb_mapping, OPB_WIdget_inst, opb_widget_attr
481             where ( $name_clause ) and opb_mapping.mapping_id = opb_widget_inst.mapping_id and
482             opb_widget_inst.instance_name like 'lkp\%' and
483             opb_widget_attr.attr_value not like '\%VW' and
484             opb_widget_inst.widget_id = opb_widget_attr.widget_id and
485             opb_widget_attr.attr_id = 2
486             order by mapping_name";
487              
488             my $sth = $dbh->prepare($sql_cmd);
489             $sth->execute;
490             while ( ( @results ) = $sth->fetchrow_array ) {
491             push @{ $lookups{$results[1]} }, $results[0];
492             push @{ $mappings{$results[0]}{LKPS} }, $results[1];
493             }
494            
495             $sth->finish;
496              
497             # ------------- Next we push the sources onto mappings
498             # ------------- and push mappings onto the sources struct
499              
500             $sql_cmd =
501             "select opb_mapping.mapping_name, opb_src.source_name
502             from opb_mapping, opb_widget_inst, opb_src
503             where ( $name_clause ) and opb_mapping.mapping_id = opb_widget_inst.mapping_id
504             and opb_widget_inst.widget_type = 1
505             and opb_src.src_id = opb_widget_inst.widget_id
506             and opb_src.source_name not like '%ETL%'";
507              
508             $sth = $dbh->prepare($sql_cmd);
509             $sth->execute;
510             while ( ( @results ) = $sth->fetchrow_array ) {
511             push @{ $mappings{$results[0]}{SRC} }, $results[1];
512             push @{ $sources{$results[1]} }, $results[0];
513             }
514             $sth->finish;
515              
516             # ------------- Next we push the targets onto mappings
517              
518             $sql_cmd =
519             "select opb_mapping.mapping_name, opb_targ.target_name
520             from opb_mapping, opb_widget_inst, opb_targ
521             where ( $name_clause ) and opb_mapping.mapping_id = opb_widget_inst.mapping_id
522             and opb_targ.target_id = opb_widget_inst.widget_id
523             and opb_targ.target_name not like '%ETL%'
524             and opb_widget_inst.widget_type = 2";
525              
526             $sth = $dbh->prepare($sql_cmd);
527             $sth->execute;
528             while ( ( @results ) = $sth->fetchrow_array ) {
529             $sql_cmd = "select count\(\*\) from $results[1]";
530             my $sth2 = $dbh->prepare($sql_cmd);
531             $sth2->execute;
532             while ( ( @r2 ) = $sth2->fetchrow_array ) {
533             $mappings{$results[0]}{COUNT} = $r2[0];
534             }
535              
536             push @{ $mappings{$results[0]}{TGT} }, $results[1];
537             push @{ $targets{$results[1]} }, $results[0];
538             }
539             $sth->finish;
540              
541             foreach $mapping ( keys %mappings ) {
542             my $srcname = $mappings{$mapping}{SRC}->[-1];
543             if ( defined $lookups{$srcname} ) {
544             $mappings{$mapping}{USED} = 1;
545             }
546             }
547              
548             return ( \%mappings, \%sources, \%targets, \%lookups );
549             }
550             # ---------------------------------- Recurse %depends
551              
552              
553             =over 3
554              
555             =item recurse( $mapping, $load_seq, $MS, $SS, $TS );
556              
557             This function populates the array reference passed as its first
558             parameter with an ordered list of informatica maps. The order is
559             such that lookups and sources are run before their targets.
560              
561             The following snippet shows typical usage employing the
562             get_mapping_structs function described above.
563              
564             @{$aref} = qw( HR80 );
565             ( $MS, $SS, $TS, $LS ) = get_mapping_structs( $aref, $dbh );
566             foreach $mapping ( keys(%{$MS}) ) {
567             recurse( $mapping, $load_seq, $MS, $SS, $TS );
568             }
569              
570             =back
571              
572             =cut
573              
574             sub recurse {
575             my ( $mapping, $load_seq, $MS, $SS, $TS ) = @_;
576             my ( $lkp, $new_trgt );
577              
578             if ( defined $MS->{$mapping}{DONE} ) {
579             return;
580             }
581              
582             if ( ! defined $MS->{$mapping}{LKPS} or ! defined $MS->{$mapping}{LKPS}[0] ) {
583             push_onto_load_seq( $MS, $load_seq, $mapping );
584             return;
585             }
586              
587             while ( $new_trgt = pop @{ $MS->{$mapping}{LKPS} } ) {
588             if ( defined $TS->{$new_trgt}[0] ) {
589             my $new_map = $TS->{$new_trgt}[0];
590             recurse( $new_map, $load_seq, $MS, $SS, $TS );
591             }
592             elsif ( ! defined $MS->{$new_trgt}{DONE} ) {
593             $MS->{$new_trgt}{DONE} = 1;
594             push_onto_load_seq( $MS, $load_seq, "No mapping: $new_trgt");
595             }
596             }
597             recurse( $mapping, $load_seq, $MS, $SS, $TS );
598             }
599             #-----------------------------------
600             sub push_onto_load_seq {
601             my ( $MS, $load_seq, $mapping ) = @_;
602              
603             push( @{$load_seq}, $mapping );
604             $MS->{$mapping}{DONE} = 1;
605             return;
606             }